[TIL]07.02

rbw·2022년 7월 2일
0

TIL

목록 보기
31/97

직사각형 요소의 모서리를 둥글게 하려면 ?

// 버튼 이름이 refreshButton 이라 하면 
refreshButton.layer.cornerRadius = 10 

Layer ?

'layer' 는 렌더링에 사용되는 뷰의 코어 애니메이션 레이어라고 한다. 일반적인 UIView와는 다르고, 코어 애니메이션에서 제공하는 클래스이다. UIView와 달리 별도의 Responder가 없어 유저 인터렉션 기능은 직접 구현 및 설정 해야한다.

UIView와는 달리 메인스레드를 사용하지 않고, 별도의 스레드를 사용한다.

UIView는 사실 CALayerwrapper 이다. UIView는 많은 것을 처리하지만 사실 어떤 그림이나 애니메이션들은 직접 제어하지 않고 내가 view에 어떤 일을 시키면 이 안의 layer 객체에서 이 일을 직접 수행한다.

예를 들어, viewbackgroundColor 설정을 해도 결국엔, layerbackgroundColor가 변하는 것이다.

컬렉션 뷰 관련 api

// 컬렉션 뷰의 수직 바운드를 막아줌. (수평방향일때 위아래 드래그 불가능하게 해줌)
collectionView.alwaysBounceVertical = false

// 만약 섹션의 크기가 부족하면 시스템이 자동으로 다음 셀을 밑으로 보내버리는데 그 부분을 방지해줌
section.orthogonalScrollingBehavior = .continuous

//  페이징을 쉽게 해주는 프로퍼티, 그룹을 가운데로 정렬해서 페이징 효과를 준다.
section.orthogonalScrollingBehavior = .groupPagingCentered

// 현재 보여지고 있는 화면에 어떤 항목이 표시되는지 알 수 있는 api
// 내부 클로저를 활용해서 처리한다.
section.visibleItemsInvalidationHandler = { (item, offset, env) in
    // 소수점 올림하는 코드, 페이징에 값을 넘기기 위해 계산 !
    let index = Int((offset.x / env.container.contentSize.width).rounded(.up))
    self.pageControl.currentPage = index
}

네비게이션과 모달

모달

모달은 사용자에게 일시적으로 집중을 요하는 컨텐츠 표시할 때 사용

따라서 사용자에게 모달로 띄운 화면이 중요하고, 필요한 경우 액션이 요구 됨을 알려줌

화면 나가기 위한 명확한 행동이 요구됨(닫기버튼, 화면 스와이프 다운 등)

네비게이션

보통 사용자들은 앱의 기능을 탐색할때, 타고 타고 들어가다가 빠져 나올 때 당황하거나 어려움을 겪음

이때 네비게이션은 사용자가 당황하지 않게끔, 자연스럽게 지나왔던 곳을 돌아가게끔 도와주는 것

종류

iOS 에서 제공해주는 시스템 모달

  • alert
  • activity views
  • share sheets
  • action sheets

개발자가 직접 제공해주는 모달

직접 제공해주는 경우, 모달 띄우는 스타일도 정해야함

  • automatic
  • fullscreen
  • popover
  • page sheet and form sheet
  • current context
  • custom

구현

뷰 컨트롤러의 present(_:animated:completion:) 메소드를 사용

iOS 에서 주요 네비게이션 스타일 3가지

  • Hierarchical Navigation : 주로 화면에서 하나 선택하면 다음 화면으로 넘어감, 많은 서비스가 선택하는 스타일 e.g) 설정앱
  • Flat Navigation : 여러 콘텐츠 카테고리 사이에서 변경되는 스타일 (탭바를 사용하는 앱) e.g) 애플 뮤직, 앱스토어
  • Content-Drive or Experience-Driven Navigation : 콘텐츠 자체가 네비게이션 스타일을 정의하는 스타일 (추천 로직이 들어간 앱) e.g) 게임, 북스

여러 스타일을 나누긴 했지만, 앱 내에서는 각 스타일을 복합적으로 사용함

주요 원칙

  • 사용자가 언제나 명확한 이동경로를 파악할 수 있게 해라
  • 정보 구조를 사용자가 이해하기 쉽고 빠르게 접근하도록 디자인 해야함
  • 사용자 제스처를 충분히 사용해라, e.g) 스와이프백
  • iOS에서 제공하는 네비게이션을 주로 사용할 것 : 네비게이션 컨트롤러, 탭바 컨트롤러 등등
  • 네비게이션 바를 이용해서 현재 어떤 컨텍스트인지 잘 보여주기
  • 탭바를 이용해서 카테고리, 또는 기능별로 나누어서 표시해라
  • 아이패드에서는 탭바 보다, 스플릿 뷰를 써라
  • 여러 페이지가 있는 경우, 페이지 컨트롤을 써라

요약

사용자가 앱내에서 화면전환간에 헤매지 않도록 도와주어야함 크게는 네비게이션, 모달을 적절히 사용해서 도움 모달은 집중을, 네비게이션은 개미지옥 탈출 을 도와줌

스택뷰 안의 이미지를 넣을 때

스택 뷰안의 이미지를 넣을때 뷰 하나를 만든 다음 넣어라.

스택 뷰에서 이미지는 자동으로 스택 뷰 너비만큼 맞춰서 늘어나기 떄문임

앱에서 사파리 웹을 띄우고 싶을 때

// import 하고 아래 코드를 작성하면 된다 (버튼 안에 넣어주거나 등등)
import SafariServices
 
guard let url = URL(string: framework.urlString) else {
    return
}

let safari = SFSafariViewController(url: url)
present(safari, animated: true)

다른 스토리보드의 뷰 컨트롤러를 띄우려면 ?

// 먼저 delegate 설정 후에 밑의 코드를 작성 하면 된다.

// 이 경우에는 컬렉션 뷰의 아이템을 선택하면 아래 코드를 수행하겠다는 의미이다.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let framework = list[indexPath.item]
        print(">>> selected: \(framework.name)")
        
        // 스토리보드의 이름과 뷰 컨트롤러의 ID를 들고 오는 부분
        let storyboard = UIStoryboard(name: "Detail", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "FrameworkDetailViewController") as! FrameworkDetailViewController

        // 데이터를 넘겨주는 부분
        vc.framework = framework

        // 만약 풀스크린으로 띄우고 싶다면 아래 코드 작성
        // vc.UIModalPresentationStyle = .fullScreen
        
        // 화면을 띄우는 부분
        present(vc, animated: true)
    }

만약 같은 스토리보드의 다른 뷰 컨트롤러를 위의 방식으로 띄우고 싶다면 storyboard에 새로운 값을 넣을 필요 없이 storyboard 키워드만 작성해서 instantiateViewController(withReuseIdentifier:) 함수를 사용하고, present에 넘겨주면 된다.

CollectionView에 Header를 추가하려면 ?

 // header 부분
datasource.supplementaryViewProvider = {(collectionView, kind, indexPath) in
guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: 
UICollectionView.elementKindSectionHeader, withReuseIdentifier: "QuickFocusHeaderView", for: indexPath) as? QuickFocusHeaderView else {
    return nil
}

let allSections = Section.allCases
let section = allSections[indexPath.section]

// section이라는 enum에 읽기 전용 프로퍼티인 title을 넘기는 모습.
header.configure(section.title)
return header
}

// Header 사이즈 구현
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(50))

let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize,
elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
section.boundarySupplementaryItems = [header]

위 코드처럼 dequeueReusableSupplementaryViewUICollectionView.elementKindSectionHeader를 사용하는것의 차이를 빼면 cell에서 사용하던 dequeueReusableCell 과 거의 동일하다.

먼저 스토리보드에 Collection Reusable View를 추가해주고 뷰 컨트롤러를 하나 만들어서 class, Identifier 에 연결을 해주고 위의 코드를 작성하면 된다

boundarySupplementaryItems는 헤더와 푸터 같은 섹션의 경계 가장자리와 여녁ㄹ된 추가적인 항목의 배열이다.

스토리보드에서 적용하려면 아래 사진에서 Prefers Large Titles를 체크하면 된다.

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 적용하지 않으려면, 이 코드를 적어 주면 된다
    self.navigationItem.largeTitleDisplayMode  = .never
}
profile
hi there 👋

0개의 댓글