iOS 응용 프로그램 에서 이미지 캐 시 에 대한 관리 와 사용 을 깊이 분석 합 니 다.
로 컬 그림 을 불 러 오 는 두 가지 방법
1.이미지 Named:방법 으로 그림 불 러 오기
이 방식 으로 그림 을 불 러 왔 습 니 다.그림 을 메모리 에 불 러 오 면 프로그램 이 종 료 될 때 까지 소각 하지 않 습 니 다.(즉,imageNamed:그림 캐 시 기능 이 있 습 니 다.다음 에 그림 에 접근 할 때 속도 가 더 빨 라 집 니 다.)
이런 방식 으로 그림 을 불 러 오 면 그림 의 메모리 관 리 는 프로그래머 의 통 제 를 받 지 않 습 니 다.
UIImage *image = [UIImage imageNamed: @“image”]
UIImage 대상 을 만 든 다 는 뜻 입 니 다.image 자체 가 그림 이 아니 라 image 가 그림 을 가리 키 는 것 입 니 다.이 대상 을 만 들 때 실제 그림 을 메모리 에 불 러 오지 않 고 그림 을 사용 할 때 불 러 옵 니 다.예 를 들 어 image 대상 을 nil 로 설정 하면 다른 대상 이 라면 강 한 포인터 가 대상 을 가리 키 지 않 으 면 이 대상 은 삭 제 됩 니 다.그러나 image=nil 이 가리 키 는 그림 자원 은 소각 되 지 않 습 니 다.
2.이미지 위 드 콘 텐 츠 OFFile:방식 으로 그림 불 러 오기
이 방법 을 사용 하여 그림 을 불 러 옵 니 다.그림 대상 을 가리 키 는 지침 이 없 거나 다른 대상 을 가리 키 면 이 그림 대상 은 다른 강력 한 지침 이 없 으 며 이 그림 대상 은 삭 제 됩 니 다.메모리 에 계속 머 물 지 않 습 니 다.
캐 시 가 없 기 때문에 같은 그림 을 여러 번 불 러 오 면 캐 시 그림 이 아 닌 여러 개의 그림 대상 이 메모 리 를 사용 합 니 다.
이 방법 을 사용 하려 면 file 의 전체 경로 가 필요 합 니 다.
NSString *imagePath = [[NSBundle mainBundle] pathForResource:imageName ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
그림 이 Images.xcassets 에 있 으 면 이 방법 을 사용 할 수 없습니다.따라서 그림 의 메모리 관 리 를 원 하지 않 는 다 면 이미지 자원 을 Images.xcassets 에 두 지 않 고 프로젝트 에 직접 끌 어 다 놓 아야 합 니 다.빠 른 대기 행렬 과 느 린 대기 행렬
우 리 는 두 개의 대기 열 을 설정 했다.하 나 는 직렬 이 고 하 나 는 병렬 이다.화면 에 절박 하 게 요 구 된 그림 이 병렬 대기 열(fastQueue)에 들 어 갑 니 다.늦게 필요 한 그림 이 직렬 대기 열(slowQueue)에 들 어 갈 수 있 습 니 다.
UITableView 의 실현 에 있어 서,이것 은 화면의 표 단원 이 fastQueue 에서 그림 을 가 져 오고,닫 힌 줄 마다 그림 을 slowQueue 에서 미리 불 러 오 는 것 을 의미한다.
지금 은 그림 을 처리 할 필요 가 없습니다.
만약 에 우리 가 서버 에서 30 개의 사건 을 포함 한 한 페이지 의 정 보 를 요청 해 야 한다 고 가정 하면 이 내용 들 이 돌아 오 기 를 요청 할 때 우 리 는 줄 을 서서 그 중의 모든 그림 을 미리 가 져 오 기 를 기다 릴 수 있다.
- (void)pageLoaded:(NSArray *)newEvents {
for (SGEvent *event in newEvents) {
[SGImageCache slowGetImageForURL:event.imageURL thenDo:nil];
}
}
slowGetImageForURL:이 방법 은 네트워크 통신 을 막 지 않 고 한 장 씩 꺼 낼 수 있 도록 그림 을 slowQueue 대기 열 에 추가 합 니 다.thendo:이 코드 블록 은 여기 서 실현 되 지 않 았 습 니 다.왜냐하면 우 리 는 아직 그림 에 대해 아무것도 할 필요 가 없 기 때 문 입 니 다.우리 가 해 야 할 일 은 로 컬 디스크 캐 시 에 있 는 지 확인 하고 언제든지 화면 에서 표를 미 끄 러 뜨 릴 때 사용 하 는 것 입 니 다.
지금 바로 그림 을 처리 해 야 합 니 다.
화면 에 표 시 된 표 는 그림 을 즉시 표시 하 기 를 원 하기 때문에 table cell 하위 클래스 에서 이 루어 집 니 다.
- (void)setEvent:(SGEvent *)event {
__weak SGEventCell *me = self;
[SGImageCache getImageForURL:event.imageURL thenDo:^(UIImage *image) {
me.imageView.image = image; }
];
}
getImageForURL:이 방법 은 그림 을 캡 처 하 는 과정 을 fastQueue 라 는 대기 열 에 추가 합 니 다.iOS 시스템 이 허용 하면 동시에 실 행 됩 니 다.그림 을 캡 처 하 는 과정 이 slow Queue 대기 열 에 존재 한다 면 fastQueue 대기 열 로 이동 하여 중복 요청 을 피 할 수 있 습 니 다.계속 비동기
잠시 만 요.getImageForURL:비동기 적 인 방법 이 아 닙 니까?그림 이 캐 시 에 있다 는 것 을 알 면서 도 메 인 스 레 드 에서 바로 사용 하고 싶 지 않 습 니까?직감 은 너 에 게 그것 이 틀 렸 다 는 것 을 알려 준다.
디스크 에 그림 을 불 러 오 는 데 너무 많은 자원 이 들 고 압축 을 푸 는 데 도 많은 자원 이 든다.미 끄 러 지 는 과정 에서 표를 설정 하고 추가 할 수 있 습 니 다.마지막 으로 표 가 미 끄 러 질 때 하고 싶 은 일 은 매우 위험 합 니 다.메 인 스 레 드 를 막 고 렉 이 걸 릴 수 있 기 때 문 입 니 다.
getImageForURL 을 사용 하면 디스크 에 불 러 오 는 동작 을 주 스 레 드 에서 벗 어 날 수 있 습 니 다.따라서 thendo:이 작업 을 마 칠 코드 블록 이 실 행 될 때 UIImage 인 스 턴 스 가 있어 서 미끄럼 이 걸 릴 위험 이 없습니다.그림 이 로 컬 캐 시 에 존재 한다 면 마무리 작업 에 사용 되 는 코드 블록 은 다음 실행 주기 에 실 행 될 것 이 며 사용 자 는 이들 의 차 이 를 알 아차 리 지 못 할 것 입 니 다.그들 은 미끄럼 이 멈 추 지 않 는 다 는 것 을 알 게 될 것 이다.
지금 은 당신 이 빨리 실행 할 필요 가 없습니다.
사용자 가 표 의 끝 부분 을 빠르게 미 끄 러 뜨리 면 수 십 개 또는 수백 개의 표 단원 이 화면 에 나타 나 fastQueue 에 그림 데 이 터 를 요청 한 후 빠르게 화면 에서 사라 집 니 다.갑자기 이 병렬 대기 열 은 실제로 필요 하지 않 은 그림 요청 을 네트워크 에 가득 채 울 것 이다.사용자 가 최종 적 으로 미끄럼 을 멈 추 었 을 때 현재 화면 에 있 는 표 셀 보 기 는 필요 하지 않 은 요청 뒤에 그림 을 요청 하기 때문에 네트워크 가 막 혔 습 니 다.
이것 이 바로 wheremoveTaskToSlow QueueForURL.이라는 방법의 발생 원인 입 니 다.
// a table cell is going off screen-
(void)tableView:(UITableView *)table
didEndDisplayingCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath*)indexPath {
// we don't need it right now, so move it to the slow queue
[SGImageCache moveTaskToSlowQueueForURL:[[(id)cell event] imageURL]];
}
이것 은 fastQueue 에서 진정 으로 신속하게 수행 해 야 할 임무 만 있 을 수 있 도록 보장 합 니 다.이전에 빠 른 실행 이 필요 하 다 고 생각 했 지만 지금 은 필요 하지 않 은 작업 이 slow Queue 로 이동 합 니 다.중점 과 선택
이미 상당히 많은 iOS 이미지 캐 시 라 이브 러 리 가 있 습 니 다.그들 중 일부 라 이브 러 리 는 일부 응용 장면 만 대상 으로 하고 일부 라 이브 러 리 는 서로 다른 장면 의 일정한 확장 성 을 제공 했다.우리 의 라 이브 러 리 는 특정한 응용 장면 을 대상 으로 하지 않 았 고 크 고 완전한 특성 도 별로 없 었 다.우리 의 사용 자 를 대상 으로 우 리 는 세 가지 기본 적 인 중점 이 있다.
중점 1:최고의 프레임 률
많은 라 이브 러 리 들 이 이 점 에 집중 하고 고도 의 맞 춤 형 과 복잡 한 방법 을 사용한다.비록 기준 이 이렇게 효과 적 이지 않 지만.우 리 는 가장 좋 은 프레임 율 이 이러한 결정 에 의 해 결정 되 는 것 을 발견 했다.
디스크 에 대한 접근(그리고 거의 모든 것)을 주 스 레 드 에서 벗 어 납 니 다.
불필요 한 디스크 접근 과 그림 압축 을 피하 기 위해 UIImage 의 메모리 캐 시 를 사용 합 니 다.
중점 2:가장 중요 한 그림 을 우선 표시 합 니 다.
대부분의 라 이브 러 리 는 대기 열 관 리 를 다른 사람의 관심 사로 만 드 는 것 을 고려한다.우리 의 응용 에 있어 서 이것 은 거의 가장 중요 한 점 이다.
정확 한 그림 을 정확 한 시간 에 화면 에 표시 하면 간단 한 문제 로 요약 할 수 있 습 니 다."우 리 는 지금 그것 을 표시 해 야 합 니까?아니면 잠시 후에 표시 해 야 합 니까?"즉시 표시 해 야 할 그림 은 병렬 로 딩 지 이 며,다른 모든 것 은 직렬 대기 열 에 추 가 됩 니 다.그동안 급 했 던 일 들 이 지금 급 하지 않 으 면 fastQueue 에서 slow Queue 로 나 뉘 어 집 니 다.또한 fastQueue 가 일 할 때 slow Queue 는 걸 려 있 는 상태 입 니 다.
이 는 급히 표시 해 야 할 그림 들 이 네트워크 에 단독으로 접근 할 수 있 도록 하 는 동시에 급히 표시 하지 않 은 그림 이 나중에 급히 표시 해 야 할 그림 이 될 수 있 도록 확보 했다.캐 시 에 저장 되 어 있 기 때문에 언제든지 표시 할 준비 가 되 어 있 기 때문이다.
포인트 3:가능 한 한 간단 한 API
대부분의 창고 가 이 점 을 해 냈 다.많은 라 이브 러 리 들 이 세부 내용 을 숨 기기 위해 UIImageView 의 분 류 를 제공 하고 많은 라 이브 러 리 들 이 그림 한 장 을 캡 처 하 는 절 차 를 가능 한 한 편리 하 게 한다.우리 가 자주 하 는 세 가지 일 에 대해 우리 의 라 이브 러 리 는 세 가지 주요 방법 을 선정 했다.
빨리 그림 한 장 잡 아.
__weak SGEventCell *me = self;[SGImageCache getImageForURL:event.imageURL thenDo:^(UIImage *image) { me.imageView.image = image;}];
줄 을 서서 우리 가 좀 있다 가 필요 한 그림 을 기다리다.
[SGImageCache slowGetImageForURL:event.imageURL thenDo:nil];
캐 시 에 급히 표시 해 야 할 그림 을 바로 표시 할 필요 가 없습니다.
[SGImageCache moveTaskToSlowQueueForURL:event.imageURL];
결론.프 리 캐 시,대기 열 관리 에 전념 하여 주 스 레 드 에서 시간 이 걸 리 는 작업 을 제거 하고 UIImage 에 내 장 된 메모리 캐 시 에 의존 하여 간단 한 패키지 에서 좋 은 결 과 를 얻 으 려 고 노력 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
View의 레이아웃 방법을 AutoLayout에서 따뜻한 손 계산으로 하면 성능이 9.26배로 된 이야기이 기사는 의 15 일째 기사입니다. 어제는 에서 이었습니다. 손 계산을 권하는 의도는 없고, 특수한 상황하에서 계측한 내용입니다 화면 높이의 10 배 정도의 contentView가있는 UIScrollView 레이아...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.