天天看點

1102 - iOS◍ 文檔: View Programming Guide for iOS -- iOS的視圖程式設計指南 第二章 windowWindows -- 簡介

Windows -- 簡介

--Every iOS application needs at least one window—an instance of the

UIWindow

class—and some may include more than one window. A window object has several responsibilities:

  • It contains your application’s visible content.
  • It plays a key role in the delivery of touch events to your views and other application objects.  
  • It works with your application’s view controllers to facilitate orientation changes.

--In iOS, windows do not have title bars, close boxes, or any other visual adornments. A window is always just a blank container for one or more views. Also, applications do not change their content by showing new windows. When you want to change the displayed content, you change the frontmost views of your window instead.

      一個app至少要有一個window,window的功能是:容納你的app 的内容、★負責觸摸事件的傳遞、與vc一起負責手機橫豎方向的改變。window自身沒有可視化的飾件,通常是一個作為一個空白的容器來容納多個vc。app不會通過展示新的window來改變視圖内容

--Most iOS applications create and use only one window during their lifetime. This window spans the entire main screen of the device and is loaded from the application’s main nib file (or created programmatically) early in the life of the application. However, if an application supports the use of an external display for video out, it can create an additional window to display content on that external display. All other windows are typically created by the system, and are usually created in response to specific events, such as an incoming phone call.

      大多數app在它們的生命期間隻建立和使用一個window。window在app生命初期通過nib file檔案或者程式設計的方式被建立。如果app支援在外設上展示視訊,那麼它是通過建立一個新的window在外設上展示視訊的。還有就是,所有的window通常都是被系統建立的,用于響應特殊的事件,例如來電顯示。

Tasks That Involve Windows -- 涉及window的task

--For many applications, the only time the application interacts with its window is when it creates the window at startup. However, you can use your application’s window object to perform a few application-related tasks:

     對大多數app而已,app唯一和window有互動的時機就是app建立window的那個時候。但是app也可以通過window來執行一些特殊的app級别的任務。

  • Use the window object to convert points and rectangles to or from the window’s local coordinate system. For example, if you are provided with a value in window coordinates, you might want to convert it to the coordinate system of a specific view before trying to use it. For information on how to convert coordinates, see Converting Coordinates in the View Hierarchy.

        使用Window對象将點和矩形與視窗的局部坐标系互相轉換。例如将window上的坐标映射為某個view的坐标系,詳情看超連結

  • Use window notifications to track window-related changes. Windows generate notifications when they are shown or hidden or when they accept or resign the key status. You can use these notifications to perform actions in other parts of your application. For more information, see Monitoring Window Changes.

       使用window的”通知“來跟蹤window級别的狀态改變。在顯示或者隐藏window時,在接收或者放棄密鑰狀态時,window都會産生window級别的通知。你可以通過監聽這些通知,寫相應的代碼,如何監聽window的改變,看超連結。

Creating and Configuring a Window -- 建立和配置window

--You can create and configure your application’s main window programmatically or using Interface Builder. In either case, you create the window at launch time and should retain it and store a reference to it in your application delegate object. If your application creates additional windows, have the application create them lazily when they are needed. For example, if your application supports displaying content on an external display, it should wait until a display is connected before creating the corresponding window.

     你要在app啟動期間建立window,并在app級别的委托對象中儲存該window的引用。額外的window對象,你要使用懶加載的方式建立。外設用的window也要在連接配接外設之後才建立。

--You should always create your application’s main window at launch time regardless of whether your application is being launched into the foreground or background. Creating and configuring a window is not an expensive operation by itself. However, if your application is launched straight into the background, you should avoid making the window visible until your application enters the foreground.

    無論你的app處于手機的背景還是前台狀态,你都要在app啟動期就建立号主要的window的。

Creating Windows in Interface Builder -- 通過界面建造器建立window

--Creating your application’s main window using Interface Builder is simple because the Xcode project templates do it for you. Every new Xcode application project includes a main nib file (usually with the name

MainWindow.xib

or some variant thereof) that includes the application’s main window. In addition, these templates also define an outlet for that window in the application delegate object. You use this outlet to access the window object in your code.

         每一個xcode的模闆都提供了一個主要的nib file給你建立window時,你可以在app的委托對象中使用outlet 來連接配接window

Important: When creating your window in Interface Builder, it is recommended that you enable the Full Screen at Launch option in the attributes inspector. If this option is not enabled and your window is smaller than the screen of the target device, touch events will not be received by some of your views. This is because windows (like all views) do not receive touch events outside of their bounds rectangle. Because views are not clipped to the window’s bounds by default, the views still appear visible but events do not reach them. Enabling the Full Screen at Launch option ensures that the window is sized appropriately for the current screen.

    重要提示:通過IB建立window對象時,切記在屬性檢查器中設定啟動選項為全屏啟動。如果你不設定為全屏啟動,那麼window可能就沒有覆寫全螢幕,沒覆寫的剩餘螢幕内發生的觸摸事件也就不會被傳遞到你的view中。★因為view的内容是不會跟随window的邊界進行裁剪的。是以window是用來傳遞事件的。

--If you are retrofitting a project to use Interface Builder, creating a window using Interface Builder is a simple matter of dragging a window object to your nib file. Of course, you should also do the following:

    把一個window對象拖到nib檔案中,就可以用IB來改造你的項目了。

  • To access the window at runtime, you should connect the window to an outlet, typically one defined in your application delegate or the File’s Owner of the nib file.

       oulet是在你的app委托對象或者nib file中定義的,是以記得将你的outlet連接配接window

  • If your retrofit plans include making your new nib file the main nib file of your application, you must also set the

    NSMainNibFile

    key in your application’s

    Info.plist

    file to the name of your nib file. Changing the value of this key ensures that the nib file is loaded and available for use by the time the

    application:didFinishLaunchingWithOptions:

    method of your application delegate is called.

        你可以在app的

Info.plist

file 中将

NSMainNibFile鍵的值設定為你的nib file,這樣你的nib file就成為了主要的nib file了。注意,此時,你要保證你的nib file在app的委托對象調用application:didFinishLaunchingWithOptions:方法前是已經加載好的,并且有效的。

--For more information about creating and configuring nib files, see Interface Builder User Guide. For information about how to load nib files into your application at runtime, see Nib Files in Resource Programming Guide.

    更多關于使用nib file的詳情,看兩個超連結。

Creating a Window Programmatically -- 以程式設計方式建立window

--If you prefer to create your application’s main window programmatically, you should include code similar to the following in the

application:didFinishLaunchingWithOptions:

method of your application delegate:

    程式設計方式建立window的話,你要在app的委托對象中寫以下代碼,swift版自己搜尋。

self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
           

--In the preceding example,

self.window

is assumed to be a declared property of your application delegate that is configured to retain the window object. If you were creating a window for an external display instead, you would assign it to a different variable and you would need to specify the bounds of the non main

UIScreen

object representing that display.

    self.window是app委托對象中的一個已經聲明了的屬性。注意外設的window不是這個屬性,是其他的屬性,你也要指派一個非主

UIScreen

對象給外設window來設定它的邊界。

--When creating windows, you should always set the size of the window to the full bounds of the screen. You should not reduce the size of the window to accommodate the status bar or any other items. The status bar always floats on top of the window anyway, so the only thing you should shrink to accommodate the status bar is the view you put into your window. And if you are using view controllers, the view controller should handle the sizing of your views automatically.

     手機的狀态欄永遠都是浮現在window上面的,你就不要多此一舉來裁剪window的尺寸了,記得全屏。但是你在window上放view的時候,就需要考慮狀态欄的布局影響在内了。

Adding Content to Your Window -- 為你的window增設内容

--Each window typically has a single root view object (managed by a corresponding view controller) that contains all of the other views representing your content. Using a single root view simplifies the process of changing your interface; to display new content, all you have to do is replace the root view. To install a view in your window, use the

addSubview:

method. For example, to install a view that is managed by a view controller, you would use code similar to the following:

    每一個window上都有一個根視圖,用于容納所有的其他視圖。你可以通過window的

addSubview:

方法來在window上安裝view。vc還有view這個屬性?好吧。執行個體代碼如下:

[window addSubview:viewController.view];
           

--In place of the preceding code, you can alternatively configure the

rootViewController

property of the window in your nib file. This property offers a convenient way to configure the root view of the window using a nib file instead of programmatically. If this property is set when the window is loaded from its nib file, UIKit automatically installs the view from the associated view controller as the root view of the window. This property is used only to install the root view and is not used by the window to communicate with the view controller.

    window還有一個

rootViewController

屬性,但是該屬性的目的隻是是為了安裝根view,而不能用于window與vc之間的通信。

--You can use any view you want for a window’s root view. Depending on your interface design, the root view can be a generic

UIView

object that acts as a container for one or more subviews, the root view can be a standard system view, or the root view can be a custom view that you define. Some standard system views that are commonly used as root views include scroll views, table views, and image views.

    根視圖可以是任何視圖,建議用系統提供的标準view

--When configuring the root view of the window, you are responsible for setting its initial size and position within the window. For applications that do not include a status bar, or that display a translucent status bar, set the view size to match the size of the window. For applications that show an opaque status bar, position your view below the status bar and reduce its size accordingly. Subtracting the status bar height from the height of your view prevents the top portion of your view from being obscured.

     無論在你的app中,手機的狀态欄是透明的還是不透明的,你的window都要設定為全屏的。但是你的view就要根據手機狀态欄是否透明來決定布局是否減去狀态欄的高度。

Note: If the root view of your window is provided by a container view controller (such as a tab bar controller, navigation controller, or split-view controller), you do not need to set the initial size of the view yourself. The container view controller automatically sizes its view appropriately based on whether the status bar is visible.

      注意,如果你的根view是由容器vc提供的,則你不需要手動設定根view的尺寸,容器vc會自動根據手機狀态欄的透明度來設定你的根view的尺寸。當然,你肯定也可以手動設定啊。其實手動設定可能會更友善。不然有很多細節你要看文檔。

Changing the Window Level -- 改變window的級别

--Each

UIWindow

object has a configurable

windowLevel

property that determines how that window is positioned relative to other windows. For the most part, you should not need to change the level of your application’s windows. New windows are automatically assigned to the normal window level at creation time. The normal window level indicates that the window presents application-related content. Higher window levels are reserved for information that needs to float above the application content, such as the system status bar or alert messages. And although you can assign windows to these levels yourself, the system usually does this for you when you use specific interfaces. For example, when you show or hide the status bar or display an alert view, the system automatically creates the needed windows to display those items.

    每一個window都有一個

windowLevel

屬性,用于決定相對于其他window而言的地位如何。預設為normal級别,一般你也很少用到這個屬性。但是,預設下,系統會根據情形自動地為特殊的window設定相應的級别,例如彈窗。

Monitoring Window Changes -- 監控window的變化

--If you want to track the appearance or disappearance of windows inside your application, you can do so using these window-related notifications:

    你可以通過window發出的以下通知,來監聽你app上的window的變化。例如window的顯示和消失,答應我,自己翻譯通知名字好嗎。

  • UIWindowDidBecomeVisibleNotification

  • UIWindowDidBecomeHiddenNotification

  • UIWindowDidBecomeKeyNotification

  • UIWindowDidResignKeyNotification

--These notifications are delivered in response to programmatic changes in your application’s windows. Thus, when your application shows or hides a window, the

UIWindowDidBecomeVisibleNotification

and

UIWindowDidBecomeHiddenNotification

notifications are delivered accordingly. These notifications are not delivered when your application moves into the background execution state. Even though your window is not displayed on the screen while your application is in the background, it is still considered visible within the context of your application.

UIWindowDidBecomeVisibleNotification

UIWindowDidBecomeHiddenNotification

是在你的app進入手機背景或者前台的時候發出的。★但是你的app進入背景執行狀态時,這兩個通知不會被發出來。

--The

UIWindowDidBecomeKeyNotification

and

UIWindowDidResignKeyNotification

notifications help your application keep track of which window is the key window—that is, which window is currently receiving keyboard events and other non touch-related events. Whereas touch events are delivered to the window in which the touch occurred, events that do not have an associated coordinate value are delivered to the key window of your application. Only one window at a time may be key.

UIWindowDidBecomeKeyNotification

UIWindowDidResignKeyNotification是在你的window成為或者辭去鍵window職務時發出的通知。所謂的鍵window就是接受“鍵盤事件”以及其他“非觸摸事件”的window。正如,觸摸事件會被傳遞到目前正在被觸摸的window中,那麼那些不與坐标系綁定的事件就會被傳遞到鍵window中,注意,一個正常的window是可以臨時擔任一個key window的,也可以随時辭去key window的身份的,而且key window一般不是一直存在,有需要你就注冊為key window就是了,雖然是系統自動根據情形賦予或者辭去你key window的身份。是以,某一個時刻,隻能存在唯一一個key window。

Displaying Content on an External Display -- 在外設顯示器上展示内容

先不看

To display content on an external display, you must create an additional window for your application and associate it with the screen object representing the external display. New windows are normally associated with the main screen by default. Changing the window’s associated screen object causes the contents of that window to be rerouted to the corresponding display. Once the window is associated with the correct screen, you can add views to it and show it just like you do for your application’s main screen.

The

UIScreen

class maintains a list of screen objects representing the available hardware displays. Normally, there is only one screen object representing the main display for any iOS-based device, but devices that support connecting to an external display can have an additional screen object available. Devices that support an external display include iPhone and iPod touch devices that have Retina displays and the iPad. Older devices, such as iPhone 3GS, do not support external displays.

Note: Because external displays are essentially a video-out connection, you should not expect touch events for views and controls in a window that is associated with an external display. In addition, it is your application’s responsibility to update the contents of the window as needed. Thus, to mirror the contents of your main window, your application would need to create a duplicate set of views for the external display’s window and update them in tandem with the views in your main window.

The process for displaying content on an external display is described in the following sections. However, the following steps summarize the basic process:

  1. At application startup, register for the screen connection and disconnection notifications.
  2. When it is time to display content on the external display, create and configure a window.
    • Use the

      screens

      property of

      UIScreen

      to obtain the screen object for the external display.
    • Create a

      UIWindow

      object and size it appropriately for the screen (or for your content).
    • Assign the

      UIScreen

      object for the external display to the

      screen

      property of the window.
    • Adjust the resolution of the screen object as needed to support your content.
    • Add any appropriate views to the window.
  3. Show the window and update it normally.

Handling Screen Connection and Disconnection Notifications -- 處理螢幕的斷開和連接配接事件。

  也是外設顯示器的内容,先不看,有需求再看。

Screen connection and disconnection notifications are crucial for handling changes to external displays gracefully. When the user connects or disconnects a display, the system sends appropriate notifications to your application. You should use these notifications to update your application state and create or release the window associated with the external display.

The important thing to remember about the connection and disconnection notifications is that they can come at any time, even when your application is suspended in the background. Therefore, it is best to observe the notifications from an object that is going to exist for the duration of your application’s runtime, such as your application delegate. If your application is suspended, the notifications are queued until your application exits the suspended state and starts running in either the foreground or background.

Listing 2-1 shows the code used to register for connection and disconnection notifications. This method is called by the application delegate at initialization time but you could register for these notifications from other places in your application, too. The implementation of the handler methods is shown in Listing 2-2.

Listing 2-1  Registering for screen connect and disconnect notifications

- (void)setupScreenConnectionNotificationHandlers
           
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
           
[center addObserver:self selector:@selector(handleScreenConnectNotification:)
           
name:UIScreenDidConnectNotification object:nil];
           
[center addObserver:self selector:@selector(handleScreenDisconnectNotification:)
           
name:UIScreenDidDisconnectNotification object:nil];
           
}
           

If your application is active when an external display is attached to the device, it should create a second window for that display and fill it with some content. The content does not need to be the final content you want to present. For example, if your application is not ready to use the extra screen, it can use the second window to display some placeholder content. If you do not create a window for the screen, or if you create a window but do not show it, a black field is displayed on the external display.

Listing 2-2 shows how to create a secondary window and fill it with some content. In this example, the application creates the window in the handler methods it uses to receive screen connection notifications. (For information about registering for connection and disconnection notifications, see Listing 2-1.) The handler method for the connection notification creates a secondary window, associates it with the newly connected screen and calls a method of the application’s main view controller to add some content to the window and show it. The handler method for the disconnection notification releases the window and notifies the main view controller so that it can adjust its presentation accordingly.

Listing 2-2  Handling connect and disconnect notifications

- (void)handleScreenConnectNotification:(NSNotification*)aNotification
           
UIScreen*    newScreen = [aNotification object];
           
CGRect        screenBounds = newScreen.bounds;
           
if (!_secondWindow)
           
_secondWindow = [[UIWindow alloc] initWithFrame:screenBounds];
           
_secondWindow.screen = newScreen;
           
// Set the initial UI for the window.
           
[viewController displaySelectionInSecondaryWindow:_secondWindow];
           
}
           
}
           
- (void)handleScreenDisconnectNotification:(NSNotification*)aNotification
           
if (_secondWindow)
           
// Hide and then delete the window.
           
_secondWindow.hidden = YES;
           
[_secondWindow release];
           
_secondWindow = nil;
           
// Update the main screen based on what is showing here.
           
[viewController displaySelectionOnMainScreen];
           
}
           
}
           

Configuring a Window for an External Display -- 為外設顯示器配置一個window

先不看

To display a window on an external screen, you must associate it with the correct screen object. This process involves locating the proper

UIScreen

object and assigning it to the window’s

screen

property. You can get the list of screen objects from the

screens

class method of

UIScreen

. The array returned by this method always contains at least one object representing the main screen. If a second object is present, that object represents a connected external display.

Listing 2-3 shows a method that is called at application startup to see if an external display is already attached. If it is, the method creates a window, associates it with the external display, and adds some placeholder content before showing the window. In this case, the placeholder content is a white background and a label indicating that there is no content to display. To show the window, this method changes the value of its

hidden

property rather than calling

makeKeyAndVisible

. It does this because the window contains only static content and is not used to handle events.

Listing 2-3  Configuring a window for an external display

- (void)checkForExistingScreenAndInitializeIfPresent
           
if ([[UIScreen screens] count] > 1)
           
// Associate the window with the second screen.
           
// The main screen is always at index 0.
           
UIScreen*    secondScreen = [[UIScreen screens] objectAtIndex:1];
           
CGRect        screenBounds = secondScreen.bounds;
           
_secondWindow = [[UIWindow alloc] initWithFrame:screenBounds];
           
_secondWindow.screen = secondScreen;
           
// Add a white background to the window
           
UIView*            whiteField = [[UIView alloc] initWithFrame:screenBounds];
           
whiteField.backgroundColor = [UIColor whiteColor];
           
[_secondWindow addSubview:whiteField];
           
[whiteField release];
           
// Center a label in the view.
           
NSString*    noContentString = [NSString stringWithFormat:@"<no content>"];
           
CGSize        stringSize = [noContentString sizeWithFont:[UIFont systemFontOfSize:18]];
           
CGRect        labelSize = CGRectMake((screenBounds.size.width - stringSize.width) / 2.0,
           
(screenBounds.size.height - stringSize.height) / 2.0,
           
stringSize.width, stringSize.height);
           
UILabel*    noContentLabel = [[UILabel alloc] initWithFrame:labelSize];
           
noContentLabel.text = noContentString;
           
noContentLabel.font = [UIFont systemFontOfSize:18];
           
[whiteField addSubview:noContentLabel];
           
// Go ahead and show the window.
           
_secondWindow.hidden = NO;
           
}
           
}
           

Important: You should always associate a screen with a window before showing the window. While it is possible to change screens for a window that is currently visible, doing so is an expensive operation and should be avoided.

As soon as the window for an external screen is displayed, your application can begin updating it like any other window. You can add and remove subviews as needed, change the contents of subviews, animate changes to the views, and invalidate their contents as needed.

Configuring the Screen Mode of an External Display -- 配置外設顯示的螢幕模式

還是先不看啊。

Depending on your content, you might want to change the screen mode before associating your window with it. Many screens support multiple resolutions, some of which use different pixel aspect ratios. Screen objects use the most common screen mode by default, but you can change that mode to one that is more suitable for your content. For example, if you are implementing a game using OpenGL ES and your textures are designed for a 640 x 480 pixel screen, you might change the screen mode for screens with higher default resolutions.

If you plan to use a screen mode other than the default one, you should apply that mode to the

UIScreen

object before associating the screen with a window. The

UIScreenMode

class defines the attributes of a single screen mode. You can get a list of the modes supported by a screen from its

availableModes

property and iterate through the list for one that matches your needs.

For more information about screen modes, see UIScreenMode Class Reference.