AppDelegate.m의 화면에 현재 표시되는 UIViewController를 가져옵니다.
UIViewController배지보기를 설정하여 화면 의 전류 가해 야 APN의 푸시 알림에 응답합니다. 하지만 어떻게 내가 얻을 수있는 UIViewController방법 application:didReceiveRemoteNotification:의 AppDelegate.m?
self.window.rootViewController-display 얻는 현재 데를 사용하려고 UIViewController했습니다. UINavigationViewController또는 다른 종류의보기 컨트롤러 일 수 있습니다. 의 그리고 visibleViewController속성 이 화면에 표시 UINavigationViewController되는 것이 좋습니다 UIViewController. 그러나 그것이 아닌 경우 UINavigationViewController에는 어떻게해야합니까?
감사합니다! 관련 코드는 다음과 가변됩니다.
AppDelegate.m
...
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//I would like to find out which view controller is on the screen here.
UIViewController *vc = [(UINavigationViewController *)self.window.rootViewController visibleViewController];
[vc performSelector:@selector(handleThePushNotification:) withObject:userInfo];
}
...
ViewControllerA.m
- (void)handleThePushNotification:(NSDictionary *)userInfo{
//set some badge view here
}
rootViewController컨트롤러 가 아닌 경우에도 사용할 수 있습니다 UINavigationController.
UIViewController *vc = self.window.rootViewController;
루트 뷰 컨트롤러를 알고지만 UI 구축 방법에 따라 다르지만 컨트롤러 계층 구조를 탐색하는 방법을 수 있습니다.
앱을 정의한 방식에 대한 자세한 내용을 알려면 힌트를 줄 수 있습니다.
편집하다 :
뷰 컨트롤러 가 아닌 최상위 뷰 를 원하면 확인할 수 있습니다.
[[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
이 견해는 믿고 믿습니다 ...
다시 말하지만 UI에 따라 다르지만 도움이 될 수 있습니다 ...
나는 항상 범주가 능숙하게 할 수있는 범주를 포함하는 솔루션을 좋아합니다.
그래서 UIWindow에 카테고리를 만들었습니다. 이제 UIWindow에서 visibleViewController를 호출 할 수 있고 컨트롤러 계층을 검색하여 가시적 인 뷰 컨트롤러를받을 수 있습니다. 탐색 및 / 또는 탭 막대 컨트롤러를 사용하는 경우 작동합니다. 제안 할 다른 유형의 기부가 가능합니다.
UIWindow + PazLabs.h (헤더 파일)
#import <UIKit/UIKit.h>
@interface UIWindow (PazLabs)
- (UIViewController *) visibleViewController;
@end
UIWindow + PazLabs.m (구현 파일)
#import "UIWindow+PazLabs.h"
@implementation UIWindow (PazLabs)
- (UIViewController *)visibleViewController {
UIViewController *rootViewController = self.rootViewController;
return [UIWindow getVisibleViewControllerFrom:rootViewController];
}
+ (UIViewController *) getVisibleViewControllerFrom:(UIViewController *) vc {
if ([vc isKindOfClass:[UINavigationController class]]) {
return [UIWindow getVisibleViewControllerFrom:[((UINavigationController *) vc) visibleViewController]];
} else if ([vc isKindOfClass:[UITabBarController class]]) {
return [UIWindow getVisibleViewControllerFrom:[((UITabBarController *) vc) selectedViewController]];
} else {
if (vc.presentedViewController) {
return [UIWindow getVisibleViewControllerFrom:vc.presentedViewController];
} else {
return vc;
}
}
}
@end
스위프트 버전
public extension UIWindow {
public var visibleViewController: UIViewController? {
return UIWindow.getVisibleViewControllerFrom(self.rootViewController)
}
public static func getVisibleViewControllerFrom(_ vc: UIViewController?) -> UIViewController? {
if let nc = vc as? UINavigationController {
return UIWindow.getVisibleViewControllerFrom(nc.visibleViewController)
} else if let tc = vc as? UITabBarController {
return UIWindow.getVisibleViewControllerFrom(tc.selectedViewController)
} else {
if let pvc = vc?.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(pvc)
} else {
return vc
}
}
}
}
Swift의 UIApplication에 대한 간단한 확장 ( UITabBarControlleriPhone의 moreNavigationController에 관심이 있음 ) :
extension UIApplication {
class func topViewController(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return topViewController(base: nav.visibleViewController)
}
if let tab = base as? UITabBarController {
let moreNavigationController = tab.moreNavigationController
if let top = moreNavigationController.topViewController where top.view.window != nil {
return topViewController(top)
} else if let selected = tab.selectedViewController {
return topViewController(selected)
}
}
if let presented = base?.presentedViewController {
return topViewController(base: presented)
}
return base
}
}
간단한 사용법 :
if let rootViewController = UIApplication.topViewController() {
//do sth with root view controller
}
완벽하게 작동합니다 :-)
육성 코드 업데이트 :
extension UIViewController {
var top: UIViewController? {
if let controller = self as? UINavigationController {
return controller.topViewController?.top
}
if let controller = self as? UISplitViewController {
return controller.viewControllers.last?.top
}
if let controller = self as? UITabBarController {
return controller.selectedViewController?.top
}
if let controller = presentedViewController {
return controller.top
}
return self
}
}
NSNotificationCenter를 통해 알림을 게시 할 수도 있습니다. 통해 뷰 컨트롤러 계층을 순회하는 것이 까다로울 수있는 여러 상황 (예 : 모달이 표시되는 경우 등)을 처리 할 수 있습니다.
예 :
// MyAppDelegate.h
NSString * const UIApplicationDidReceiveRemoteNotification;
// MyAppDelegate.m
NSString * const UIApplicationDidReceiveRemoteNotification = @"UIApplicationDidReceiveRemoteNotification";
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
[[NSNotificationCenter defaultCenter]
postNotificationName:UIApplicationDidReceiveRemoteNotification
object:self
userInfo:userInfo];
}
각 View Controller에서 :
-(void)viewDidLoad {
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(didReceiveRemoteNotification:)
name:UIApplicationDidReceiveRemoteNotification
object:nil];
}
-(void)viewDidUnload {
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:UIApplicationDidReceiveRemoteNotification
object:nil];
}
-(void)didReceiveRemoteNotification:(NSDictionary *)userInfo {
// see http://stackoverflow.com/a/2777460/305149
if (self.isViewLoaded && self.view.window) {
// handle the notification
}
}
이 접근 방식을 사용하여 알림을 수신하고 여러보기 컨트롤러에서 사용하는 경우 업데이트해야하는 컨트롤을 계측 할 수 있습니다. 이 경우 init 메소드에서 추가 / 제거 옵저버 호출을 처리하십시오.
iOS 8이 모든 것을 망쳤습니다. iOS 7에서는 UITransitionView모달 표시가있을 때마다보기 계층 구조에 새로운 기능 이 있습니다 UINavigationController. 어쨌든 여기 내 코드는 최고의 VC를 가져옵니다. 호출 getTopMostViewController하면 VC와 같은 메시지를 보낼 수 presentViewController:animated:completion있습니다. 모달 VC를 제시하는 데 사용할 수있는 VC를 제공하는 것이 그 UINavigationController안에 포함 된 VC와 같은 컨테이너 클래스에서 중지하고 반환 할 가능성이 준비 됩니다. 그렇게하기 위해 코드를 조정하는 것이 어렵지 않습니다. iOS 6, 7 및 8의 다양한 상황 에서이 코드를 테스트했습니다. 버그가 있으면 알려주십시오.
+ (UIViewController*) getTopMostViewController
{
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
if (window.windowLevel != UIWindowLevelNormal) {
NSArray *windows = [[UIApplication sharedApplication] windows];
for(window in windows) {
if (window.windowLevel == UIWindowLevelNormal) {
break;
}
}
}
for (UIView *subView in [window subviews])
{
UIResponder *responder = [subView nextResponder];
//added this block of code for iOS 8 which puts a UITransitionView in between the UIWindow and the UILayoutContainerView
if ([responder isEqual:window])
{
//this is a UITransitionView
if ([[subView subviews] count])
{
UIView *subSubView = [subView subviews][0]; //this should be the UILayoutContainerView
responder = [subSubView nextResponder];
}
}
if([responder isKindOfClass:[UIViewController class]]) {
return [self topViewController: (UIViewController *) responder];
}
}
return nil;
}
+ (UIViewController *) topViewController: (UIViewController *) controller
{
BOOL isPresenting = NO;
do {
// this path is called only on iOS 6+, so -presentedViewController is fine here.
UIViewController *presented = [controller presentedViewController];
isPresenting = presented != nil;
if(presented != nil) {
controller = presented;
}
} while (isPresenting);
return controller;
}
암호
Swift 3 에서 훌륭한 스위치 케이스 구문 을 사용하는 접근 방식은 다음과 가능 합니다.
extension UIWindow {
/// Returns the currently visible view controller if any reachable within the window.
public var visibleViewController: UIViewController? {
return UIWindow.visibleViewController(from: rootViewController)
}
/// Recursively follows navigation controllers, tab bar controllers and modal presented view controllers starting
/// from the given view controller to find the currently visible view controller.
///
/// - Parameters:
/// - viewController: The view controller to start the recursive search from.
/// - Returns: The view controller that is most probably visible on screen right now.
public static func visibleViewController(from viewController: UIViewController?) -> UIViewController? {
switch viewController {
case let navigationController as UINavigationController:
return UIWindow.visibleViewController(from: navigationController.visibleViewController ?? navigationController.topViewController)
case let tabBarController as UITabBarController:
return UIWindow.visibleViewController(from: tabBarController.selectedViewController)
case let presentingViewController where viewController?.presentedViewController != nil:
return UIWindow.visibleViewController(from: presentingViewController?.presentedViewController)
default:
return viewController
}
}
}
기본 아이디어는 zirinisp의 답변과 동일하며 더 빠른 Swift 3 구문을 사용합니다.
용법
라는 이름의 파일을 만들려고합니다 UIWindowExtension.swift. import UIKit명령문 이 포함되어 있는지 확인 하고 위의 확장 코드를 복사하십시오 .
호출 측에서는 특정 뷰 컨트롤러없이 사용할 수 있습니다 .
if let visibleViewCtrl = UIApplication.shared.keyWindow?.visibleViewController {
// do whatever you want with your `visibleViewCtrl`
}
또는 특정 뷰 컨트롤러에서 보이는 뷰 컨트롤러에 접근 할 수 있다고 생각하는 :
if let visibleViewCtrl = UIWindow.visibleViewController(from: specificViewCtrl) {
// do whatever you want with your `visibleViewCtrl`
}
도움이 되길 바랍니다!
다른 모든 솔루션보다 코드가 적습니다.
Objective-C 버전 :
- (UIViewController *)getTopViewController {
UIViewController *topViewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
while (topViewController.presentedViewController) topViewController = topViewController.presentedViewController;
return topViewController;
}
Swift 2.0 버전 : (신용이 Steve.B로 이동)
func getTopViewController() -> UIViewController {
var topViewController = UIApplication.sharedApplication().delegate!.window!!.rootViewController!
while (topViewController.presentedViewController != nil) {
topViewController = topViewController.presentedViewController!
}
return topViewController
}
모달 앱에서 어느 곳에서 작동합니다.
스위프트에서 zirinisp의 답변 :
extension UIWindow {
func visibleViewController() -> UIViewController? {
if let rootViewController: UIViewController = self.rootViewController {
return UIWindow.getVisibleViewControllerFrom(rootViewController)
}
return nil
}
class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
if vc.isKindOfClass(UINavigationController.self) {
let navigationController = vc as UINavigationController
return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController)
} else if vc.isKindOfClass(UITabBarController.self) {
let tabBarController = vc as UITabBarController
return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)
} else {
if let presentedViewController = vc.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(presentedViewController.presentedViewController!)
} else {
return vc;
}
}
}
}
용법 :
if let topController = window.visibleViewController() {
println(topController)
}
각 ViewController의 제목을 다음 아래 코드로 현재 ViewController의 제목을 가져옵니다.
-(void)viewDidUnload {
NSString *currentController = self.navigationController.visibleViewController.title;
그런 다음 제목으로 확인하십시오.
if([currentController isEqualToString:@"myViewControllerTitle"]){
//write your code according to View controller.
}
}
내 것이 낫다! :)
extension UIApplication {
var visibleViewController : UIViewController? {
return keyWindow?.rootViewController?.topViewController
}
}
extension UIViewController {
fileprivate var topViewController: UIViewController {
switch self {
case is UINavigationController:
return (self as! UINavigationController).visibleViewController?.topViewController ?? self
case is UITabBarController:
return (self as! UITabBarController).selectedViewController?.topViewController ?? self
default:
return presentedViewController?.topViewController ?? self
}
}
}
왜 앱 델리게이트에서 푸시 알림 코드를 처리하지 않습니까? 뷰와 직접 관련이 있습니까?
뷰의 window속성에 값이 있는지 확인하여 UIViewController의 뷰가 현재 표시되어 있는지 확인할 수 있습니다 . 자세한 내용은 여기를 참조 하십시오 .
@zirinisp 답변에 추가하십시오.
파일을 작성하고 이름을 UIWindowExtension.swift후 다음 스 니펫을 제안하십시오.
import UIKit
public extension UIWindow {
public var visibleViewController: UIViewController? {
return UIWindow.getVisibleViewControllerFrom(self.rootViewController)
}
public static func getVisibleViewControllerFrom(vc: UIViewController?) -> UIViewController? {
if let nc = vc as? UINavigationController {
return UIWindow.getVisibleViewControllerFrom(nc.visibleViewController)
} else if let tc = vc as? UITabBarController {
return UIWindow.getVisibleViewControllerFrom(tc.selectedViewController)
} else {
if let pvc = vc?.presentedViewController {
return UIWindow.getVisibleViewControllerFrom(pvc)
} else {
return vc
}
}
}
}
func getTopViewController() -> UIViewController? {
let appDelegate = UIApplication.sharedApplication().delegate
if let window = appDelegate!.window {
return window?.visibleViewController
}
return nil
}
다음과 같이 어디서나 사용하십시오. :
if let topVC = getTopViewController() {
}
@zirinisp에게 감사합니다.
위의 NSNotificationCenter 게시물과 관련하여 (죄송합니다. 아래에 의견을 게시 할 수 없습니다 ...)
일부에서-[NSConcreteNotification allKeys] 오류가 발생하는 경우. 그것을 변경하십시오 :
-(void)didReceiveRemoteNotification:(NSDictionary *)userInfo
이에 :
-(void)didReceiveRemoteNotification:(NSNotification*)notif {
NSDictionary *dict = notif.userInfo;
}
이것은 나를 위해 일했습니다. 컨트롤러가 다른 많은 대상이 있으므로 이전 답변이 작동하지 않는 것입니다.
AppDelegate 클래스 내에서 먼저 원합니다.
var window: UIWindow?
그런 다음 기능에서
let navigationController = window?.rootViewController as? UINavigationController
if let activeController = navigationController!.visibleViewController {
if activeController.isKindOfClass( MyViewController ) {
println("I have found my controller!")
}
}
이것이 내가 시도한 가장 좋은 방법입니다. 누군가에게 도움이 능력 ...
+ (UIViewController*) topMostController
{
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
return topController;
}
extension UIApplication {
/// The top most view controller
static var topMostViewController: UIViewController? {
return UIApplication.shared.keyWindow?.rootViewController?.visibleViewController
}
}
extension UIViewController {
/// The visible view controller from a given view controller
var visibleViewController: UIViewController? {
if let navigationController = self as? UINavigationController {
return navigationController.topViewController?.visibleViewController
} else if let tabBarController = self as? UITabBarController {
return tabBarController.selectedViewController?.visibleViewController
} else if let presentedViewController = presentedViewController {
return presentedViewController.visibleViewController
} else {
return self
}
}
}
이것으로 쉽게 탑 포스트 뷰를 얻을 수 있습니다.
let viewController = UIApplication.topMostViewController
주목할 것은 UIAlertController가 현재 표시되어 있습니다. UIApplication.topMostViewController마무리 것 UIAlertController입니다.
jungledev의 답변 스위프트 2.0 버전
func getTopViewController() -> UIViewController {
var topViewController = UIApplication.sharedApplication().delegate!.window!!.rootViewController!
while (topViewController.presentedViewController != nil) {
topViewController = topViewController.presentedViewController!
}
return topViewController
}
나는를 위해 카테고리를 만들어 UIApplication와 visibleViewControllers속성입니다. 주요 아이디어는 매우 간단합니다. 나는 스위 즐링 viewDidAppear및 viewDidDisappear메소드 UIViewController. 에 viewDidAppear있어서의의의 ViewController 스택에 추가된다. 에 viewDidDisappear있어서의의의 ViewController 스택으로부터 제거된다. 약한 의 참조 를 저장 NSPointerArray하는 대신 사용 합니다. 이 접근 방식은 모든 viewController 계층에 적용됩니다.NSArrayUIViewController
UIApplication + VisibleViewControllers.h
#import <UIKit/UIKit.h>
@interface UIApplication (VisibleViewControllers)
@property (nonatomic, readonly) NSArray<__kindof UIViewController *> *visibleViewControllers;
@end
UIApplication + VisibleViewControllers.m
#import "UIApplication+VisibleViewControllers.h"
#import <objc/runtime.h>
@interface UIApplication ()
@property (nonatomic, readonly) NSPointerArray *visibleViewControllersPointers;
@end
@implementation UIApplication (VisibleViewControllers)
- (NSArray<__kindof UIViewController *> *)visibleViewControllers {
return self.visibleViewControllersPointers.allObjects;
}
- (NSPointerArray *)visibleViewControllersPointers {
NSPointerArray *pointers = objc_getAssociatedObject(self, @selector(visibleViewControllersPointers));
if (!pointers) {
pointers = [NSPointerArray weakObjectsPointerArray];
objc_setAssociatedObject(self, @selector(visibleViewControllersPointers), pointers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return pointers;
}
@end
@implementation UIViewController (UIApplication_VisibleViewControllers)
+ (void)swizzleMethodWithOriginalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {
Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
BOOL didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swizzleMethodWithOriginalSelector:@selector(viewDidAppear:)
swizzledSelector:@selector(uiapplication_visibleviewcontrollers_viewDidAppear:)];
[self swizzleMethodWithOriginalSelector:@selector(viewDidDisappear:)
swizzledSelector:@selector(uiapplication_visibleviewcontrollers_viewDidDisappear:)];
});
}
- (void)uiapplication_visibleviewcontrollers_viewDidAppear:(BOOL)animated {
[[UIApplication sharedApplication].visibleViewControllersPointers addPointer:(__bridge void * _Nullable)self];
[self uiapplication_visibleviewcontrollers_viewDidAppear:animated];
}
- (void)uiapplication_visibleviewcontrollers_viewDidDisappear:(BOOL)animated {
NSPointerArray *pointers = [UIApplication sharedApplication].visibleViewControllersPointers;
for (int i = 0; i < pointers.count; i++) {
UIViewController *viewController = [pointers pointerAtIndex:i];
if ([viewController isEqual:self]) {
[pointers removePointerAtIndex:i];
break;
}
}
[self uiapplication_visibleviewcontrollers_viewDidDisappear:animated];
}
@end
https://gist.github.com/medvedzzz/e6287b99011f2437ac0beb5a72a897f0
스위프트 3 버전
UIApplication + VisibleViewControllers.swift
import UIKit
extension UIApplication {
private struct AssociatedObjectsKeys {
static var visibleViewControllersPointers = "UIApplication_visibleViewControllersPointers"
}
fileprivate var visibleViewControllersPointers: NSPointerArray {
var pointers = objc_getAssociatedObject(self, &AssociatedObjectsKeys.visibleViewControllersPointers) as! NSPointerArray?
if (pointers == nil) {
pointers = NSPointerArray.weakObjects()
objc_setAssociatedObject(self, &AssociatedObjectsKeys.visibleViewControllersPointers, pointers, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return pointers!
}
var visibleViewControllers: [UIViewController] {
return visibleViewControllersPointers.allObjects as! [UIViewController]
}
}
extension UIViewController {
private static func swizzleFunc(withOriginalSelector originalSelector: Selector, swizzledSelector: Selector) {
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
override open class func initialize() {
if self != UIViewController.self {
return
}
let swizzlingClosure: () = {
UIViewController.swizzleFunc(withOriginalSelector: #selector(UIViewController.viewDidAppear(_:)),
swizzledSelector: #selector(uiapplication_visibleviewcontrollers_viewDidAppear(_:)))
UIViewController.swizzleFunc(withOriginalSelector: #selector(UIViewController.viewDidDisappear(_:)),
swizzledSelector: #selector(uiapplication_visibleviewcontrollers_viewDidDisappear(_:)))
}()
swizzlingClosure
}
@objc private func uiapplication_visibleviewcontrollers_viewDidAppear(_ animated: Bool) {
UIApplication.shared.visibleViewControllersPointers.addPointer(Unmanaged.passUnretained(self).toOpaque())
uiapplication_visibleviewcontrollers_viewDidAppear(animated)
}
@objc private func uiapplication_visibleviewcontrollers_viewDidDisappear(_ animated: Bool) {
let pointers = UIApplication.shared.visibleViewControllersPointers
for i in 0..<pointers.count {
if let pointer = pointers.pointer(at: i) {
let viewController = Unmanaged<AnyObject>.fromOpaque(pointer).takeUnretainedValue() as? UIViewController
if viewController.isEqual(self) {
pointers.removePointer(at: i)
break
}
}
}
uiapplication_visibleviewcontrollers_viewDidDisappear(animated)
}
}
https://gist.github.com/medvedzzz/ee6f4071639d987793977dba04e11399
디버그 또는 릴리스로 앱을 실행중인 경우 항상 빌드 구성을 확인하십시오.
중요 참고 : 디버그 모드에서 앱을 실행하지 테스트 할 수 없습니다
이것은 나의 해결책이었다
'IT' 카테고리의 다른 글
| Bootstrap 3 Mobile의 메뉴 / Navbar에서 슬라이드 (0) | 2020.07.16 |
|---|---|
| Android : 텍스트가 입력되지 않은 경우 AutoCompleteTextView에 제안 표시 (0) | 2020.07.15 |
| 일반 배열의 요소 제거 (0) | 2020.07.15 |
| R에서 당신을위한 제안 제안 (0) | 2020.07.15 |
| Jenkins 파이프 라인 작업 공간 정리 (0) | 2020.07.15 |