[iOS] SceneDelegate에 대한 학습

SceneDelegate

AppDelegate & SceneDelegate

  • AppDelegate

iOS 13 미만

Process LifeCycle UI LifeCycle
App Launched Entered Foreground
App Terminate Became Active
... ...

iOS 13이상

AppDelegate SceneDelegate
Process LifeCycle UI LifeCycle
Scene LifeCycle Entered Foreground
Session Created Became Active
Session Discarded

iOS12까지는 하나의 앱은 하나의 window로 구성되어 있었다.
iOS13부터는 window의 개념이 scene으로 변경되었으며, 하나의 앱은 여러개의 scene을 가질수 있게 되었다.
다시 말해 하나의 앱에서 여러개의 scene을 보여줄수 있게 되었다.

SceneDelegate

AppDelegate의 역할 중 UI의 상태를 알 수 있는 UILifeCycle에 대한 부분을 SceneDelegate가 하게 되었다.

SceneDelegate의 생명주기

  1. [SceneDelegate] scene(_:, willConnectTo:, options:)

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    guard let _ = (scene as? UIWindowScene) else { return }
    }

    scene이 앱에 추가될 때 호출. 단 여기서 ViewController와 같은 클래스 객체를 만들어 사용할 때, 아직 viewDidLoad()가 호출되지 않음

  2. sceneDidDisconnect(_ 🙂

    func sceneDidDisconnect(_ scene: UIScene) {
    // Called as the scene is being released by the system.
    // This occurs shortly after the scene enters the background, or when its session is discarded.
    // Release any resources associated with this scene that can be re-created the next time the scene connects.
    // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    scene의 연결이 해제될 때 호출

  3. sceneDidBecomeActive(_: )

    func sceneDidBecomeActive(_ scene: UIScene) {
    // Called when the scene has moved from an inactive state to an active state.
    // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
    }

    app switcher에서 선택되는 등 scene과의 상호작용이 시작될 때 호출

    • app switcher : 홈버튼을 두번누르거나 아이폰 하단에서 위로 스와이프 했을 때 현재 실행중인 앱들이 보이는 화면
  4. sceneWillResignActive(_:)

    func sceneWillResignActive(_ scene: UIScene) {
    // Called when the scene will move from an active state to an inactive state.
    // This may occur due to temporary interruptions (ex. an incoming phone call).
    print("[SceneDelegate] sceneWillResignActive(_ scene: UIScene)")
    }

    사용자가 scene과의 상호작용을 중지할 때 호출(다른 화면으로의 전환과 같은 경우)

  5. sceneWillEnterForeground(_:)

    func sceneWillEnterForeground(_ scene: UIScene) {
    // Called as the scene transitions from the background to the foreground.
    // Use this method to undo the changes made on entering the background.
    print("[SceneDelegate] sceneWillEnterForeground(_ scene: UIScene)")
    }

    scene이 foreground로 진입할 때 호출

  6. sceneDidEnterBackground(_:)

    func sceneDidEnterBackground(_ scene: UIScene) {
    // Called as the scene transitions from the foreground to the background.
    // Use this method to save data, release shared resources, and store enough scene-specific state information
    // to restore the scene back to its current state.
    print("[SceneDelegate] sceneDidEnterBackground(_ scene: UIScene)")
    }

    scene이 background로 진입할 때 호출

AppDelegate 생명주기

AppDelegate - Scene LifeCycle

AppDelegate에는 Session LifeCycle에 대한 역할이 추가되었다.
SceneSession은 앱에서 생성한 모든 scene의 정보를 관리한다.

// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}

Scene?

UIKit은 UIWindowScene 객체를 사용하는 앱 UI의 각 인스턴스를 관리한다. Scene에는 UI의 하나의 인스턴스를 나타내는 windows와 view controllers가 들어있다. 또한, 각 scene에 해당하는 UIWindowSceneDelegate 객체를 가지고 있고, 이 객체는 UIKit과 앱 간의 상호작용을 조정하는데 사용된다.
Scene들은 같은 메모리와 앱 프로세스 공간을 공유하면서 서로 동시에 실행된다. 결과적으로 하나의 앱은 여러 Scene과 Scene delegate 객체를 동시에 활성화 할 수 있다.
(Scenes - Apple Development Document)

Scene Session?

UISceneSession 객체는 Scene의 고유의 런타임 인스턴스를 관리한다. 사용자가 앱에 새로운 Scene을 추가하거나 요청하면, 시스템은 그 Scene을 추적하는 session 객체를 생성한다. 그 Session에는 고유한 식별자와 scene의 구성 세부사항(configuration details)가 들어있다.
UIKit은 session 정보를 그 Scene 자체의 생명주기동안 유지하고 app switcher에서 사용자가 그 Scene을 클로징하는 것에 대응하여 그 session을 파괴한다.
session 객체는 직접 생성하지 않고 UIKit이 앱의 사용자 인터페이스에 대응하여 생성한다.
또한, 아래 함수를 통해서 UIKit에 새로운 Scene과 Session을 프로그래밍적 방식으로 생성할 수 있다.
(UISceneSession - Apple Development Document)

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration 
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>)

iOS13부터 AppDelegate의 역할

  1. 앱의 데이터 구조를 초기화 하는 것
  2. 앱의 Scenes의 환경설정(Configuration)
  3. 앱 밖에서발생한 알림(베터리 부족, 다운로드 완료 등)에 대응
  4. 특정한 Scenes, views, view controllers에 한정되지 않고 앱 자체를 타겟하는 이벤트에 대응하는 것
  5. 애플 푸쉬 알림 서브스와 같이 실행시 요구되는 모든 서비스를 등록
    (UIApplicationDelegate - Apple Development Document)

Deployment Target이 iOS 13 미만인 상황에서는?

iOS12이하는 단일 window 환경임으로, 아래와 같이 Scene처리를 제거할 수 있다.

  1. SceneDelegate.swift 제거
  2. AppDelegate에서 UISceneSession 관련 두개의 메소드 제거
  3. SceneDelegate로 옮겨진 window 프로퍼티를 AppDelegate로 옮기기
    var window: UIWindow?
  4. info.plist에서 Scene과 관련된 Manifest인 Application Scene Manifest 삭제

[Django 06] SQLite 모델 만들기

이제 모델을 만들겁니다.

장고 프로젝트 폴더로 이동합니다.
아래 명령어를 실행합니다.
마이그레이트를 하는건데, 기본 설정을 잡아주는것으로 알고 있습니다.

python3 manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  No migrations to apply.

모델 만들기

모델 : 부가적인 메타데이터를 가진 데이터베이스의 구조(layout)
- 데이터에 관한 단 하나의, 가장 확실한 진리의 원천.
장고는 DRY(Dont Repeat Yourself) 원칙을 따름
http://wiki.c2.com/?DontRepeatYourself

Question과 Choice 모델을 만들거고, Question은 질문과 일자를 가지고 있을 겁니다.
Choice는 두개의 필드를 가집니다.(the text of the choice and a vote tally). 각 Choice는 Question과 관련있습니다.

polls/models.py 파일을 생성합니다.

from django.db import models

# 모델의 활성화
# 앱을 위한 데이터베이스 스키마 생성(CREATE TABLE)
# Question과 Choice 객체에 접근하기 위한 Python 데이터베이스 접근 API 생성

# 현재 프로젝트에게 polls 앱이 설치 되었다는것을 알려야 한다. (앱을 꼈다 뺐다 할수 있다.)
# 앱을 현재의 프로젝트에 포함시키기 위해서는 settings.py > INSTALLED_APPS 설정에 추가해야 한다. 
# PollsConfig 클래스는 polls/apps.py 파일 내에 존재 -> polls.apps.PollsConfig




# django.db.models.Model subclass
# 데이터베이스의 각 Field는 클래스의 인스턴스로 표현
    
# 각 필드 
# CharField는 문자 필드
# DateTimeField는 날짜와 시간(datetime) 필드 등

# 각 필드의 인스턴스 이름(question_text)은 
# 기계가 읽기 좋은 형식(machine-friendly format)의 데이터베이스 필드 이름은
# 필드명을 Python 코드에서 사용할 수 있으며, 데이터베이스에서는 컬럼명으로 사용 

# 필드 클래스의 생성자에 선택적인 첫번째 위치 인수를 전달하여 사람이 읽기 좋은(human-readable)
# 이름을 지정할 수도 있다. -> Question.pub_date

# 몇몇 Field 클래스는 인수가 필요합니다. (CharField의 경우 max_length)
# Field는 다양한 선택적 인수들을 가질수 있다.
class Question(models.Model):    
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

#  ForeignKey를 사용한 관계설정
#  각각의 Choice가 하나의 Question에 관계된다는 정보.
#  question = models.ForeignKey(Question, on_delete=models.CASCADE)
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

위와 같은 코드를 작성하고 다음 명령을 통해 변경시킨 모델을 migration으로 저장하고 싶다고 장고에게 알려준다.

python3 manage.py makemigrations polls

-> 결과
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice

잘 보면 polls 밑에 migrations 폴더와 0001 이름의 모델이 생성되었다.

아래 코드를 실행해보면, 내부적으로 어떤 SQL 문장이 실행되는지 알수 있다.

python3 manage.py sqlmigrate polls 0001

-> 결과테테테ㅌ
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL, "pub_date" datetime NOT NULL);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" integer NOT NULL REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;

테이블 이름은 앱 이름 + _ + 모델의 이름으로 자동 생성한다.
기본키 id도 자동 생성되고, 재지정이 가능하다.
외래 키 필드명에 "_id" 이름이 자동으로 추가된다. (재지정 가능)

python manage.py migrate

migrate 명령은 아직 적용되지 않은 마이그레이션을 모두 수집해 이를 실행하며(Django는 django_migrations 테이블을 두어 마이그레이션 적용 여부를 추적한다), 이 과정을 통해 모델에서의 변경 사항들과 뎅터베이스의 스키마의 동기화가 이루어진다.

마이그레이션은 매우 기능이 강력하여, 데이터베이스나 테이블을 수정하지 않고 모델의 반복적인 변경을 가능하게 해준다. 동작중인 데이터베이스를 자료 손실없이 업그레이드 하는 데 최적화 되어 있다.

모델의 변경을 만드는 세단계의 지침

1. (moles.py에서) 모델을 변경
2. python manage.py makemigrations 
 -> 변경사항에 대해 마이그레이션을 만듬
3. python manage.py migrate
 -> 변경 사항을 데이터베이스에 적용

manage.py 유틸리티로 어떤 일들을 할 수 있는지 django-admin 문서를 읽어보세요.

[Pyhon] scraping 작성중

파이썬으로 뭔가 데이터를 만들어서 앱을 만들려고 한다.
참 만들만한게 없다는 생각이 들어서.. 스크래핑을 학습중이다.

아래 코드는 스크래핑을 통해 파일로 저장하는 샘플 코드이다.

import requests

# res = requests.get("http://naver.com")
res = requests.get("http://google.com")

#print("응답코드:", res.status_code)

# if res.status_code == requests.codes.ok:
#     print("정상입니다.")
# else:
#     print("오류", requests.codes.ok)

# 오류 발생시 바로 종료
res.raise_for_status()
print("스크래핑 진행중")


print(len(res.text))

# 파일로 저장하기
with open("mygoogle.html", "w", encoding="utf8") as f:
    f.write(res.text)


  • 참고 자료 - 나도코딩 님의 영상 강의
  • https://www.youtube.com/watch?v=yQ20jZwDjTE&list=PLMsa_0kAjjrd8hYYCwbAuDsXZmHpqHvlV&index=4

vi 명령어

vi 명령어

vi 파일명
vi +n 파일명
vi +/검색어 파일명
vi -R 파일명 : 읽기 전용

vi -r 파일명 : 문서 복구

명령 / 입력 모드

vi 편집 명령

i : 현재 커서 입력
a : 커서 한칸 오른쪽 앱력
A : 현재행 가장 마지막에 입력
o : 현재행 다음에 한줄 삽입 후 입력
O : 현재행 위에 한줄 삽입 후 입력
s : 현재 커서 한글자 삭제후 입력
S : 현재 행 삭제후 입력
R : 문서 수정 모드
x : 문자 하나 삭제

u : 실행한 작업 취소
:redo : 취소한작업을 재실행

k : 상
h : 좌
l : 우
j : 하

n[이동키] : n만큼 이동

0 : 라인 맨 앞으로
$ : 라인 맨 뒤로
w : 오른쪽으로 한단어 이동
b : 왼쪽으로 한단어 이동

gg: 첫행으로
G: 마지막행으로
ngg: n행으로 이동

v : 알파벳 문자 단위로 영역 지정
V : 행 단위로 영역 지정

c : 삭제후 입력모드 전환. 다른키와 조합후 사용
cc : 행전체 삭제후 입력모드
d : 삭제. 다른키와 조합후 사용
dd : 행 전체 삭제
y : 텍스트 복사
yy : 행 복사
p : 붙여넣기

~ : 대소문자 전화
. : 마지막 실행한 명령을 반복 실행

문자 검색

/찾을내용 : 하일라이트로 표시
n : 다음
N : 이전

치환
:s/찾을내용/바꿀내용. 시작위치부터 첫번째로 검색한것만 바꾼다
:%s/찾을내용/바꿀내용
:%s/찾을내용/바꿀내용/c

ubuntu에서 python cgi 연동하기

CGI 실행 허용을 위한 설정

  1. .py확장자를 CGI로 실행하도록 아파치 설정
sudo vi /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        ServerName www.magpie.com
        DocumentRoot 루트경로
        <Directory 루트경로>
                AddHandler cgi-script .py
                Options ExecCGI
        </Directory>

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

2. cgi 기능 켜기

sudo a2enmod cgi

3. 아파치 서버 재기동

sudo service apache2 restart

4. 테스트 파일 추가

#!/usr/bin/python3
print("content-type:text/html; charset=UTF-8\n")

5. 파일에 권한 변경

sudo chmod a+x helloworld.py

6. 오류 발생시 로그 확인

 sudo tail -f /var/log/apache2/error.log

python lib – opencv-python

pyautogui에서 이미지 관련 처리를 하기 위해서 사용되는 라이브러리이다.

간략한 내용은 아래를 참조하고 더 자세한 내용이 필요하다면 링크를 따라가서 공부해보시라.

opencv 용어 설명

OpenCV(Open Source Computer Vision)은 실시간 컴퓨터 비전을 목적으로 한 프로그래밍 라이브러리이다. 원래는 인텔이 개발하였다. 실시간 이미지 프로세싱에 중점을 둔 라이브러리이다. 인텔CPU에서 사용되는 경우 속도의 향상을 볼 수 있는 IPP(Intel Performance Primitives)를 지원한다. 이 라이브러리는 윈도리눅스 등에서 사용 가능한 크로스 플랫폼이며 오픈소스BSD 허가서 하에서 무료로 사용할 수 있다. OpenCV는 TensorFlow , TorchPyTorch 및 Caffe의 딥러닝프레임워크를 지원한다.

출처 : https://ko.wikipedia.org/wiki/OpenCV

ios 아카이브에 불필요 앱 삭제

XCode에서 아카이브를 생성할 경우에 보기 싫은 앱들이 나타날 경우가 있다. 개인 작업하는 것들이 회사에 나타난다거나.. 등등

이럴때 아래와 같이 해당 경로로 이동해서 해당 앱 번들 아이디를 지워주고 XCode를 재실행 해주면 더이상 나타나지 않는다.
XCode설정에서 자동으로 동기화 해주는 기능이 꺼져있어야만, 자동으로 다시 생성하지 않을 것이다

ㅊ~/Library/Developer/Xcode/Products/해당 앱 번들 아이디 제거