개요

오토레이아웃 → 자동으로 그리는것

 

화면을 그릴려면 해당 뷰의 위치를 알아야 한다.

위치를 고정한다. → 앵커를 건다.

사이즈 설정

앵커를 걸고 사이즈를 설정하면 iOS에서 자동으로 계산해서 뷰를 그려준다.

 

option/alt 키를 누르면 사이즈가 나온다.

 

값 수정하는 방법

constraint 자체를 눌러서 값 수정이 가능하다.

객체를 선택한 후 Size inspector 탭에서 constraint 를 선택해서 값 수정도 가능하다.

 

constraint 제거하는 방법

문서 개요창에서 값 선택해서 제거 가능

Resolve Auto Layout Issues 에서 Clear Constraints 를 선택해서 한번에 제거도 가능

 

constraints 자동 추가

안잡혀 있는 constraint 를 자동으로 추가해준다.

 

 

 

수직/수평 정렬

align 을 설정하면 뷰의 객체의 크기를 스크린을 반으로 나누어서 위치를 계산한다.

 

xcode는 스크린의 크기를 알고 스크린을 반으로 나눈 값에서 뷰의 크기를 뺀 나머지 값을 자동으로 설정해준다. 따라서, 정렬을 잡아주면 뷰의 크기나 위치 중 하나만 잡아주어도 된다.

 

 

 

 

 

 

 

오토레이아웃 기본 정리

 

 

💡
X 축: 두 개의 위치(좌, 우) 값 중 하나를 잡아주고 뷰의 크기(Width) 를 잡아주면 Xcode 는 디바이스의 스크린의 크기를 알기 때문에 스크린크기 - 위치(좌) - 뷰의 크기(Width) = 위치(우) 를 자동으로 잡아준다.

 

 

 

 

 

 

 

 

 

'iOS > Swift' 카테고리의 다른 글

iOS의 비동기 관리  (0) 2021.09.05
DispatchQueue.main.sync 사용 시 주의사항  (0) 2021.09.05
DispatchQueue의 의존성  (0) 2021.09.05
DispatchQueue 특징  (0) 2021.09.05
비동기에서의 NSLock() 간단 비교  (0) 2021.09.05

참고 강의 링크

 

GCD와 Operation

 

GCD와 Operation의 차이

코드 예시

 

 

Synchronous(동기) VS Asynchronous(비동기)

syns: 다른 스레드에 보낸 작업을 '기다리고' 자신의 다음 작업을 처리한다.

async: 다른 스레드에 보낸 작업을 '기다리지 않고' 자신의 다음 작업을 처리한다.

 

동기 개념

 

비동기 개념

 

 

Serial(직렬) VS Concurrent(동시)

serial: 다른 '하나의 스레드'에 작업을 보낸다.

concurrent: 다른 '여러 스레드'에 작업을 보낸다.

 

Serial 큐 개념

 

Concurrent 큐 개념

 

'iOS > Swift' 카테고리의 다른 글

오토레이아웃 - 개념  (0) 2021.10.25
DispatchQueue.main.sync 사용 시 주의사항  (0) 2021.09.05
DispatchQueue의 의존성  (0) 2021.09.05
DispatchQueue 특징  (0) 2021.09.05
비동기에서의 NSLock() 간단 비교  (0) 2021.09.05

사이트 링크

 

[iOS - swift] DispatchQueue.main.sync 사용 시 주의사항 (Deadlock)

기초: Sync vs Async vs Serial vs Concurrent 개념 Deadlock (교착 상태) 두 개 이상의 process 및 thread가 서로 상대방의 작업이 끝나기만을 기다리고 있어서 task들을 처리하지 못하는 상태 ex) deadlock Seri..

ios-development.tistory.com

 

'iOS > Swift' 카테고리의 다른 글

오토레이아웃 - 개념  (0) 2021.10.25
iOS의 비동기 관리  (0) 2021.09.05
DispatchQueue의 의존성  (0) 2021.09.05
DispatchQueue 특징  (0) 2021.09.05
비동기에서의 NSLock() 간단 비교  (0) 2021.09.05

참고 사이트 링크

참고 사이트 링크

 

Global의 concurrent 특성

global은 concurrent 특성으로 여러 스레드에서 병행 처리 하기때문에 의존성 있게 데이터 관리를 할 수 없다.

var money = 10000

DispatchQueue.global().async {
    buy()
}

DispatchQueue.global().async {
    buy()
}

func buy() {
    money = money - 1000
    print(money)
}

9000

9000

 

 

main의 serial 특성

main은 serial 특성으로 다른 하나의 스레드에 작업을 넘겨주기 때문에 의존성 있게 데이터를 처리하게 된다.

var money = 10000

DispatchQueue.main.async {
    buy()
}

DispatchQueue.main.async {
    buy()
}

func buy() {
    money = money - 1000
    print(money)
}

9000

8000

'iOS > Swift' 카테고리의 다른 글

iOS의 비동기 관리  (0) 2021.09.05
DispatchQueue.main.sync 사용 시 주의사항  (0) 2021.09.05
DispatchQueue 특징  (0) 2021.09.05
비동기에서의 NSLock() 간단 비교  (0) 2021.09.05
12.2.2. 영화관 정보 API  (0) 2021.09.02

참고 사이트 링크

 

스레드를 사용할 때에 비해서, DispatchQueue가 얻을 수 있는 이점

  1. 스레드를 만들고 관리하는 것을 시스템이 하기 때문에 훨씬 간결하다. 시스템은 현재 시스템 상태와 자원에 따라 유동적으로 스레드 수를 조절할 수 있고, 종종 더 빠르게 작업을 시작할 수도 있다.
  2. Serial의 경우는, 작업의 수행순서가 보장되기 때문에 lock을 사용하지 않고도 동기화가 가능해진다. 덕분에 불필요한 커널 모드 진입을 최소화 할 수 있다.(물론 여러개의 SerialQueue가 같은 자원에 접근하게 하면 문제가 된다.)
  3. 스레드를 만들때 커널 영역과 유저 영역 메모리를 모두 확보해야하는 비용이 드는데, DispatchQueue는 이러한 비용이 들지 않는다.
  4. DispatchQueue를 통해 생성된 스레드는 클록되지 않고 계속해서 연산을 수행한다.

그 외에도 DispatchQueue가 가지는 특징

  1. DispatchQueue의 순차성은 한 Queue 단위에서만 적용된다.
  2. 아무리 Queue를 많이 만들어도, 동시에 수행되는 작업의 수는 시스템에 의해 결정된다.
  3. 시스템은 새로이 수행할 작업을 결정할 때, Queue의 우선순위를 고려한다.
  4. Queue에 작업이 들어갈 때, 이미 실행할 준비가 완료된 상태여야 한다.

'iOS > Swift' 카테고리의 다른 글

DispatchQueue.main.sync 사용 시 주의사항  (0) 2021.09.05
DispatchQueue의 의존성  (0) 2021.09.05
비동기에서의 NSLock() 간단 비교  (0) 2021.09.05
12.2.2. 영화관 정보 API  (0) 2021.09.02
12.3. 영화관 목록 화면 구현하기  (0) 2021.09.02

비동기로 동일 함수 실행

비동기로 같은 함수를 실행하게 되면 동시에 실행해서 같은 결과 값을 내게 됩니다.

import Foundation

var money = 10000

DispatchQueue.global().async {
    buy()
}

DispatchQueue.global().async {
    buy()
}

func buy() {
    money = money - 1000
    print(money)
}

9000

9000

 

 

sleep으로 동시 호출 방지

하나의 스레드가 실행될때 잠시 멈추게 하여 실행 간격에 차이를 둘 수도 있습니다.

var money = 10000

DispatchQueue.global().async {
    buy()
}

DispatchQueue.global().async {
    sleep(1)
    buy()
}

func buy() {
    money = money - 1000
    print(money)
}

9000

8000

 

 

lock으로 동시 호출 방지

만약 실행 간격에 차이를 두는것이 아니라 '하나의 스레드가 함수를 사용 중일때, 다른 스레드에서 접근을 못하게 하려면?'

var money = 10000
let lock = NSLock()

DispatchQueue.global().async {
    buy()
}

DispatchQueue.global().async {
    buy()
}

func buy() {
    lock.lock(); defer {lock.unlock()}
    money = money - 1000
    print(money)
}

9000

8000

 

이렇듯 NSLock()으로 lock을 걸면 시간 간격 차이를 두는 것과 같은 출력값이 나오게 됩니다.

순서는 이렇습니다.

Thread 1 buy() 실행, lock() -> 다른 스레드에서 접근 못함 -> Thread 2 buy() 대기 -> Thread 1 buy() 실행 후 unlock() -> 다른 스레드에서 접근 가능 -> Thread 2 buy() 실행, lock() -> 다른 스레드에서 접근 못함 -> Thread 2 buy() 실행 후 unlock()

 

 

다른 스레드 사용 방지

unlock으로 잠금해제를 하지 않게 된다면? 다른 스레드에서 접근을 하지 못한채로 끝나게 되겠죠.

var money = 10000
let lock = NSLock()

DispatchQueue.global().async {
    buy()
}

DispatchQueue.global().async {
    buy()
}

func buy() {
    lock.lock()
    money = money - 1000
    print(money)
}

9000

'iOS > Swift' 카테고리의 다른 글

DispatchQueue의 의존성  (0) 2021.09.05
DispatchQueue 특징  (0) 2021.09.05
12.2.2. 영화관 정보 API  (0) 2021.09.02
12.3. 영화관 목록 화면 구현하기  (0) 2021.09.02
이미지 비동기 처리하기  (0) 2021.08.14

Request URI

http://swiftapi.rubypaper.co.kr:2029/theater/list

 


요청

요청할 인자값 목록

항목 데이터 타입 샘플 값 설명
s_page 정수 1 페이지 번호
s_list 정수 100 페이지 크기
type 문자열 json 데이터 형식

 

URI 샘플

http://swiftapi.rubypaper.co.kr:2029/theater/list?s_page=1&s_list=100&type=json

 


응답

응답 값 샘플

 

요청에 따른 응답 내역

항목 샘플 데이터
_id 1.0
상영관명 MMC 만경관 1관
연락처 257-2041
소재지도로명주소 대구광역시 중구 국채보상로 547 (종로 1가)
위도 35.8709275
경도 128.5904236
소재지우편번호  
소재지지번주소  

 

TheaterCell 클래스

import UIKit

class TheaterCell: UITableViewCell {
    
    // 상영관명
    @IBOutlet var name: UILabel!
    // 연락처
    @IBOutlet var tel: UILabel!
    // 주소
    @IBOutlet var addr: UILabel!
}

 

TheaterListController 클래스

API를 호출하고 영화관 정보를 읽어온다.

import UIKit

class TheaterListController: UITableViewController {
    
    // API를 통해 불러온 데이터를 저장할 배열 변수
    var list = [NSDictionary]()
    // 읽어올 데이터의 시작위치
    var startPoint = 0
    
    override func viewDidLoad() {
        // API를 호출한다.
        self.callTheaterAPI()
    }
    
    func callTheaterAPI() {
        
        // 1. URL을 구성하기 위한 상수값을 선언한다.
        let requestURI = "http://swiftapi.rubypaper.co.kr:2029/theater/list" // API 요청 주소
        let sList = 100 // 불러올 데이터 개수
        let type = "json" // 데이터 형식
        
        // 2. 인자값들을 모아 URL 객체로 정의한다.
        let urlObj = URL(string: "\(requestURI)?s_page=\(self.startPoint)&s_list=\(sList)&type=\(type)")
        
        do {
            // 3. NSString 객체를 이용하여 API를 호출하고 그 결과값을 인코딩된 문자열로 받아온다.
            let stringdata = try NSString(contentsOf: urlObj!, encoding: 0x80_000_422)
            
            // 4. 문자열로 받은 데이터를 UTF-8로 인코딩처리한 Data로 변환한다.
            let encdata = stringdata.data(using: String.Encoding.utf8.rawValue)
            
            do {
                // 5. Data 객체를 파싱하여 NSArray 객체로 변환한다.
                let apiArray = try JSONSerialization.jsonObject(with: encdata!, options: []) as? NSArray
                
                // 6. 읽어온 데이터를 순회하면서 self.list 배열에 추가한다
                for obj in apiArray! {
                    self.list.append(obj as! NSDictionary)
                }
                
            } catch {
                // 경고창 형식으로 오류 메시지를 표시해준다.
                let alert = UIAlertController(title: "실패",
                                              message: "데이터 분석이 실패하였습니다",
                                              preferredStyle: .alert)
                
                alert.addAction(UIAlertAction(title: "확인", style: .cancel))
                self.present(alert, animated: false)
            }
            // 7. 읽어와야 할 다음 페이지의 데이터 시작 위치를 구해 저장해둔다.
            self.startPoint += sList
            
        } catch {
            // 경고창 형식으로 오류 메시지를 표시해준다.
            let alert = UIAlertController(title: "실패",
                                          message: "데이터를 불러오는데 실패하였습니다",
                                          preferredStyle: .alert)
            
            alert.addAction(UIAlertAction(title: "확인", style: .cancel))
            self.present(alert, animated: false)
        }
    }
}

 

테이블 목록 구현

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.list.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // self.list 배열에서 행에 맞는 데이터를 꺼냄
    let obj = self.list[indexPath.row]
    
    // 재사용 큐로부터 tCell 식별자에 맞는 셀 객체를 전달받음
    let cell = tableView.dequeueReusableCell(withIdentifier: "tCell") as! TheaterCell
    
    cell.name?.text = obj["상영관명"] as? String
    cell.tel?.text = obj["연락처"] as? String
    cell.addr?.text = obj["소재지도로명주소"] as? String
    
    return cell
}

 

 

 

 

 

 

 

'iOS > Swift' 카테고리의 다른 글

DispatchQueue 특징  (0) 2021.09.05
비동기에서의 NSLock() 간단 비교  (0) 2021.09.05
12.2.2. 영화관 정보 API  (0) 2021.09.02
이미지 비동기 처리하기  (0) 2021.08.14
뷰 컨트롤러 직접 호출에 의한 화면 전환  (0) 2021.08.09

https://piquant-oyster-f84.notion.site/10-1-2-a2049d2d81134eb69ba0f040daee98ec

 

10.1.2. 이미지 비동기 처리하기

비동기(Asynchronize) 처리 기법

piquant-oyster-f84.notion.site

 

'iOS > Swift' 카테고리의 다른 글

DispatchQueue 특징  (0) 2021.09.05
비동기에서의 NSLock() 간단 비교  (0) 2021.09.05
12.2.2. 영화관 정보 API  (0) 2021.09.02
12.3. 영화관 목록 화면 구현하기  (0) 2021.09.02
뷰 컨트롤러 직접 호출에 의한 화면 전환  (0) 2021.08.09

뷰 컨트롤러에서 직접 호출하는 방식을 프레젠테이션 방식이라고 합니다.

구현하는 방법을 알아보겠습니다.

 

뷰 컨트롤러 호출 구현

화면 UI 구성

이동할 뷰 컨트롤러에 Storyboard ID 지정

화면 전환을 구현할 버튼 객체 선언 및 뷰컨트롤러 호출 구현

@IBAction func moveNext(_ sender: Any) {
  // 이동할 뷰 컨트롤러 객체를 StoryBoardID 정보를 이용하여 참조
  let uvc = self.storyboard!.instantiateViewController(withIdentifier: "SecondVC")

  // 화면 전환할 때의 애니메이션 타입
  uvc.modalTransitionStyle = UIModalTransitionStyle.coverVertical

  // 인자값으로 뷰 컨트롤러 인스턴스를 넣고 프레젠트 메소드 호출
  self.present(uvc, animated: true)
}

 

이전 화면으로 돌아가기

뷰 컨트롤러 파일 만들기

SecondViewController.swift 파일 생성 후 UIViewController 상속

 

두번째 화면에 뷰 컨트롤러 할당

SecondViewController 에 이전 페이지 메소드 구현

import UIKit

class SecondViewController: UIViewController {
    
    @IBAction func back(_ sender: Any) {
    	// dismiss 로 호출 해제
        self.presentingViewController?.dismiss(animated: true)
    }
}

 

호출을 구현할 때에는 주체가 뷰 컨트롤러 자신이지만, 

self.present(uvc, animated: true)

호출을 해제(dismiss)할 때에는 호출을 한 대상(이전 ViewController)에게 요청하는 것이다.

self.presentingViewController?.dismiss(animated: true)

 

이전 화면과 이후 화면은 서로 참조 관계에 있다.

이전 화면(ViewController)은 presentedViewController 속성에 저장되 있는 포인터를 통해 이후 화면(SecondViewController)을 참조하고, 이후 화면(SecondViewController)는 presentingViewController 속성에 저장되 있는 포인터를 통해 이전 화면(ViewController)를 참조하게 된다.

'iOS > Swift' 카테고리의 다른 글

DispatchQueue 특징  (0) 2021.09.05
비동기에서의 NSLock() 간단 비교  (0) 2021.09.05
12.2.2. 영화관 정보 API  (0) 2021.09.02
12.3. 영화관 목록 화면 구현하기  (0) 2021.09.02
이미지 비동기 처리하기  (0) 2021.08.14

+ Recent posts