Learning Cocoa with Objective-C/Cocoa Overview and Foundation/Introduction to Cocoa
Cocoa provides a rich layer of functionality on which you can build applications. Its comprehensive object-oriented API complements a large number of technologies that Mac OS X provides. Some of these technologies are inherited from the NeXTSTEP operating system. Others are based on the BSD Unix heritage of Mac OS X's core. Still others come from the original Macintosh environment and have been updated to work with a modern operating system. In many cases, you take advantage of these underlying technologies transparently, and you get the use of them essentially "for free." In some cases, you might use these technologies directly, but because of the way Cocoa is structured, they are a simple and direct API call away.
This chapter provides an overview of the Mac OS X programming environment and Cocoa's place in it. You will then learn about the two frameworks—Foundation and Application Kit (or AppKit)—that make up the Cocoa API, as well as the functionality that they provide.
The Mac OS X Programming Environment
Mac OS X provides five principal application environments:
- A set of procedural APIs for working with Mac OS X. These interfaces were initially derived from the earlier Mac OS Toolbox APIs and modified to work with Mac OS X's protected memory environment and preemptive task scheduling. As a transitional API, Carbon gives developers a clear way to migrate legacy applications to Mac OS X without requiring a total rewrite. Adobe Photoshop 7.0 and Microsoft Office v. X are both examples of "Carbonized" applications. For more information on Carbon, see /Developer/Documentation/Carbon or Learning Carbon (O'Reilly).
- A set of object-oriented APIs derived from NeXT's operating-system technologies that take advantage of many features from Carbon. Programming with the Cocoa API is the focus of this book. Many applications that ship with Mac OS X, such as Mail and Stickies, are written in Cocoa. In addition, many of Apple's latest applications, such as iPhoto, iChat, and iDVD2, are built on top of Cocoa.
- A robust and fast virtual-machine environment for running applications developed using the Java Development Kit. Java applications are typically very portable and can run unchanged, without recompilation, on many different computing environments.
- BSD Unix
- The BSD layer of Mac OS X that provides a rich, robust, and mature set of tools and system calls. The standard BSD tools, utilities, APIs, and functions are available to applications. A command-line environment also exists as part of this layer.
- The compatibility environment in which the system runs applications originally written for Mac OS 8 or Mac OS 9 that have not been updated to take full advantage of Mac OS X. Classic is essentially a modified version of Mac OS 9 running inside a process that has special hooks into other parts of the operating system. Over time, Classic is becoming less interesting as more applications are ported to run natively in Mac OS X.
To some degree, all of these application environments rely on other parts of the system. Figure 1-1 gives a layered, albeit simplified, illustration of Mac OS X's application environments and their relationship to the other primary parts of the operating system.
As you can see from Figure 1-1, each of Mac OS X's application environments relies upon functionality provided by deeper layers of the operating system. This functionality is roughly broken into two major sections: Core Foundation, which provides a common set of application and core services to the Cocoa, Carbon, and Java frameworks, and the kernel environment, which is the underlying Unix-based core of the operating system.
Cocoa is an advanced object-oriented framework for building applications that run on Apple's Mac OS X. It is an integrated set of shared object libraries, a runtime system, and a development environment. Cocoa provides most of the infrastructure that graphical user applications typically need and insulates those applications from the internal workings of the core operating system.
Think of Cocoa as a layer of objects acting as both mediator and facilitator between programs that you build and the operating system. These objects span the spectrum from simple wrappers for basic types, such as strings and arrays, to complex functionality, such as distributed computing and advanced imaging. They are designed to make it easy to create a graphical user interface (GUI) application and are based on a sophisticated infrastructure that simplifies the programming task.
Cocoa-based applications are not just limited to using the features in the Cocoa frameworks. They can also use all of the functionality of the other frameworks that are part of Mac OS X, such as Quartz, QuickTime, OpenGL, ColorSync, and many others. And since Mac OS X is built atop Darwin, a solid BSD-based system, Cocoa-based applications can use all of the core Unix system functions and get as close to the underlying filesystem, network services, and devices as they need to.
The History of Cocoa
Cocoa has actually been around a long time—almost as long as the Macintosh itself. That is because it is, to a large extent, based on OpenStep, which was introduced to the world as NeXTSTEP in 1987, along with the elegant NeXT cube. At the time, the goal of NeXTSTEP was to, as only Steve Jobs could say, "create the next insanely great thing." It evolved through many releases, was adopted by many companies as their development and deployment environment of choice, and received glowing reviews in the press. It was, and continues to be, solid technology based on a design that was years ahead of anything else in the market.
NeXTSTEP was built on top of BSD Unix from UC Berkeley and the Mach microkernel from Carnegie-Mellon University. It utilized Display PostScript from Adobe — allowing the same code, using the PostScript page description language — to display documents on screen and to print to paper. NeXTSTEP came with a set of libraries, called "frameworks," and tools to enable programmers to build applications using the Objective-C language.
In 1993 NeXT exited the hardware business to concentrate on software. NeXTSTEP was ported to the Intel x86 architecture and released. Other ports were performed for the SPARC, Alpha, and PA-RISC architectures. Later, the frameworks and tools were revised to run on other operating systems, such as Windows and Solaris. These revised frameworks became known as OpenStep.
Fast forward to 1996. Apple had been working unsuccessfully on a next-generation operating system, known as Copland, to replace the venerable Mac OS 7. Their efforts were running amok and they decided to look outside for the foundation of the new OS. The leading contender seemed to be BeOS, but in a surprise move, Apple acquired NeXT, citing its strengths in development software and operating environments for both the enterprise and Internet markets. As part of this merger, Apple embarked on the development of Rhapsody, a development of the NeXTSTEP operating system fused with the classic Mac OS. Over the next five years, Rhapsody evolved into what was released as Mac OS X 10.0. As part of that evolution, OpenStep became Cocoa.
Mac OS X remains very much a Unix system; the Unix side of Mac OS X is just hidden from users unless they really want to use it. Its full power, however, is available to you, the programmer, to utilize. Not only can you take advantage of the power, you can actually look under the hood and see how it all works. The source code to the underpinnings of Mac OS X can be found as part of Apple's Darwin initiative (http://www.developer.apple.com/darwin).
Cocoa's Feature Set
At its foundation, Cocoa provides basic types such as strings and arrays, as well as basic functions such as byte swapping, parsing, and exception handling. Cocoa also provides utilities for memory management, utilities for archiving and serializing objects, and access to kernel entities and services such as tasks, ports, run loops, timers, threads, and locks.
On top of this foundation, Cocoa provides a set of user-interface widgets with quite a bit of built-in functionality. This functionality includes such expected things as undo and redo, drag and drop, and copy and paste, as well as lots of bonus features such as spell checking that can be enabled in any Cocoa component that accepts text. You will see how much of this functionality works while you work through the tutorials in this book.
- Imaging and printing
- Mac OS X's imaging and printing model is called Quartz and is based on Adobe's Portable Document Format (PDF). Unlike previous versions of Mac OS, the same code and frameworks are used to draw the onscreen image and to send output to printers. You'll get firsthand experience drawing with Quartz in Chapter 7, and with printing in Chapter 12.
Apple's color management and matching technology, ColorSync , is built into Quartz, ensuring that colors in documents are automatically color-corrected for any device on which they are printed or displayed. Any time an image is displayed in a Cocoa window or printed, its colors are automatically rendered correctly according to any color profile embedding in the image along with profiles for the display or printer.
- Internationalization and localization
- Cocoa's well-designed internationalization architecture allows applications to be localized easily into multiple languages. Cocoa keeps the user-interface elements separate from the executable, enabling multiple localizations to be bundled with an application. The underlying technology is the same that is used by Mac OS X to ship a single build of the OS with many localizations. This technology is covered in Chapter 14.
Because Cocoa uses Unicode as its native character set, applications can easily handle all the world's living languages. The use of Unicode eliminates many character-encoding hassles. To help you handle non-Unicode text, Cocoa provides functionality to help you translate between Unicode and the other major character sets in use today.
- Text and fonts
- Cocoa offers a powerful set of text services that can be readily adapted by text-intensive applications. These services include kerning, ligatures, tab formatting, and rulers, and they can support text buffers as large as the virtual memory space. The text system also supports embedded graphics and other inline attachments. You'll work this text system firsthand in Chapter 11.
Cocoa supports a variety of font formats, including the venerable Adobe PostScript (including Types 1, 3, and 42), the TrueType format defined by Apple in the late 1980s and adopted by Microsoft in Windows 3.1, and the new OpenType format, which merges the capabilities of both PostScript and TrueType.
- Exported application services
- Cocoa applications can make functionality available to other applications, as well as to end users, through two mechanisms: scripting with AppleScript and via Services.
AppleScript enables users to control applications directly on their system, including the operating system itself. Scripts allow even relatively unskilled users to automate common tasks and afford skilled scripters the ability to combine multiple applications to perform more complex tasks. For example, a script that executes when a user logs in could open the user's mail, look for a daily news summary message, and open the URLs from the summary in separate web-browser windows. Scripts have access to the entire Mac OS X environment, as well as other applications. For example, a script can launch the Terminal application, issue a command to list the running processes, and use the output for some other purpose.
Services, available as a submenu item of the application menu, allow users to use functionality of an application whenever they need to. For example, you can highlight some text in an application and choose the "Make New Sticky Note" service. This will launch the Stickies application (/Applications), create a new Sticky, and put the text of your selection into it. This functionality is not limited to text; it can work with any data type.
- Component technologies
- One of the key advantages of Cocoa as a development environment is its capability to develop programs quickly and easily by assembling reusable components. With the proper programming tools and a little work, you can build Cocoa components that can be packaged and distributed for use by others. End-user applications are the most familiar use of this component technology in action. Other examples include the following:
- Bundles containing executable code and associated resources that programs can load dynamically
- Frameworks that other developers can use to create programs
- Palettes containing custom user-interface objects that other developers can drag and drop into their own user interfaces
Cocoa's component architecture allows you to create and distribute extensions and plug-ins easily for applications. In addition, this component architecture enables Distributed Objects, a distributed computing model that takes unique advantage of Cocoa's abilities.
The Cocoa Frameworks
Cocoa is composed of two object-oriented frameworks: Foundation (not to be confused with Core Foundation) and Application Kit. These layers fit into the system as shown in Figure 1-2.
The classes in Cocoa's Foundation framework provide objects and functionality that are the basis, or "foundation," of Cocoa and that do not have an impact on the user interface. The AppKit classes build on the Foundation classes and furnish the objects and behavior that your users see in the user interface, such as windows and buttons; the classes also handle things like mouse clicks and keystrokes. One way to think of the difference in the frameworks is that Cocoa's Foundation classes provide functionality that operates under the surface of the application, while the AppKit classes provide the functionality for the user interface that the user sees.
You can build Cocoa applications in three languages: Objective-C, Java, and AppleScript. Objective-C was the original language in which NeXTSTEP was developed and is the "native language" of Cocoa. It is the language that we will work with throughout this book. During the early development of Mac OS X (when it was still known as Rhapsody), a layer of functionality—known as the Java Bridge—was added to Cocoa, allowing the API to be used with Java. Support has been recently added for AppleScript in the form of AppleScript Studio, which allows AppleScripters to hook into the Cocoa frameworks to provide a comprehensive Aqua-based GUI to their applications.
The brainchild of Brad Cox, Objective-C is a very simple language. It is a superset of ANSI C with a few syntax and runtime extensions that make object-oriented programming possible. It started out as just a C preprocessor and a library, but over time developed into a complete runtime system, allowing a high degree of dynamism and yielding large benefits. Objective-C's syntax is uncomplicated, adding only a small number of types, preprocessor directives, and compiler directives to the C language, as well as defining a handful of conventions used to interact with the runtime system effectively.
Objective-C is a very dynamic language. The compiler throws very little information away, which allows the runtime to use this information for dynamic binding and other uses. We'll be covering the basics of Objective-C in Chapter 3. Also, there is a complete guide to Objective-C, Inside Mac OS X: The Objective-C Language, included as part of the Mac OS X Developer Tools installation. You can find this documentation in the /Developer/Documentation/Cocoa/ObjectiveC folder.
Java is a cross-platform, object-oriented, portable, multithreaded, dynamic, secure, and thoroughly buzzword-compliant programming language developed by James Gosling and his team at Sun Microsystems in the 1990s. Since its introduction to the public in 1995, Java has gained a large following of programmers and has become a very important language in enterprise computing.
Cocoa provides a set of language bindings that allow you to program Cocoa applications using Java. Apple provides Java packages corresponding to the Foundation and Application Kit frameworks. Within reason, you can mix the APIs from the core Java packages (except for the Swing and AWT APIs) with Cocoa's packages.
For many years, AppleScript has provided an almost unmatched ability to control applications and many parts of the core Mac OS. This allows scripters to set up workflow solutions that combine the power of many applications. AppleScript combines an English-like language with many powerful language features, including list and record manipulation. The introduction of AppleScript Studio in December 2001, as well as its final release along with Mac OS X 10.2, allows scripters the ability to take their existing knowledge of AppleScript and build Cocoa-based applications quickly using Project Builder and Interface Builder.
Coverage of AppleScript Studio is beyond the scope of this book. To learn more about AppleScript Studio, see Building Applications with AppleScript Studio located in /Developer/Documentation/CoreTechnologies/AppleScriptStudio/BuildApps_AppScrptStudio.
The Foundation Framework
The Foundation framework is a set of over 80 classes and functions that define a layer of base functionality for Cocoa applications. In addition, the Foundation framework provides several paradigms that define consistent conventions for memory management and traversing collections of objects. These conventions allow you to code more efficiently and effectively by using the same mechanisms with various kinds of objects. Two examples of these conventions are standard policies for object ownership (who is responsible for disposing of objects) and a set of standard abstract classes that enumerate over collections. Figure 1-3 shows the major groupings into which the Foundation classes fall.
The Foundation framework includes the following:
- The root object class, NSObject
- Classes representing basic data types, such as strings and byte arrays
- Collection classes for storing other objects
- Classes representing system information and services
Programming Types and Operations
The Foundation framework provides many basic types, including strings and numbers. It also furnishes several classes whose purpose is to hold other objects—the array and dictionary collections classes. You'll learn more about these data types—and how to use them—throughout the chapters in this book, starting in Chapter 4.
- Cocoa's string class, NSString, supplants the familiar C programming data type char * to represent character string data. String objects contain Unicode characters rather than the narrow range of characters afforded by the ASCII character set, allowing them to contain characters in any language, including Chinese, Arabic, and Hebrew. The string classes provide an API to create both mutable and immutable strings and to perform string operations such as substring searching, string comparison, and concatenation.
String scanners take strings and provide methods for extracting data from them. While scanning, you can change the scan location to rescan a portion of the string or to skip ahead a certain number of characters. Scanners can also consider or ignore case.
- Collections allow you to organize and retrieve data in a logical manner. The collections classes provide arrays using zero-based indexing, dictionaries using key-value pairs, and sets that can contain an unordered collection of distinct or nondistinct elements.
The collection classes can grow dynamically, and they come in two forms: mutable and immutable. Mutable collections, as their name suggests, can be modified programmatically after the collection is created. Immutable collections are locked after they are created and cannot be changed.
- Data and values
- Data and value objects let simple allocated buffers, scalar types, pointers, and structures be treated as first-class objects. Data objects are object-oriented wrappers for byte buffers and can wrap data of any size. When the data size is more than a few memory pages, virtual memory management can be used. Data objects contain no information about the data itself, such as its type; the responsibility for how to use the data lies with the programmer.
For typed data, there are value objects. These are simple containers for a single data item. They can hold any of the scalar types, such as integers, floats, and characters, as well as pointers, structures, and object addresses, and allow object-oriented manipulation of these types. They can also provide functionality such as arbitrary precision arithmetic.
- Dates and times
- Date and time classes offer methods for calculating temporal differences, displaying dates and times in any desired format, and adjusting dates and times based on location (i.e., time zone).
- Exception handling
- An exception is a special condition that interrupts the normal flow of program execution. Exceptions let programs handle exceptional error conditions in a graceful manner. For example, an application might interpret saving a file in a write-protected directory as an exception and provide an appropriate alert message to the user.
Operating System Entities and Services
The Foundation framework provides classes to access core operating-system functionality such as locks, threads, and timers. These services all work together to create a robust environment in which your application can run.
- Run loops
- The run loop is the programmatic interface to objects managing input sources. A run loop processes input for sources such as mouse and keyboard events from the window system, ports, timers, and other connections. Each thread has a run loop automatically created for it. When an application is started, the run loop in the default thread is started automatically. Run loops in threads that you create must be started manually. We'll talk about run loops in detail in Chapter 8.
- The notification-related classes implement a system for broadcasting notifications of changes within an application. An object can specify and post a notification, and any other object can register itself as an observer of that notification. This topic will also be covered in Chapter 8.
- A thread is an executable unit that has its own execution stack and is capable of independent input/output (I/O). All threads share the virtual-memory address space and communication rights of their task. When a thread is started, it is detached from its initiating thread and runs independently. Different threads within the same task can run on different CPUs in systems with multiple processors.
- A lock is used to coordinate the operation of multiple threads of execution within the same application. A lock can be used to mediate access to an application's global data or to protect a critical section of code, allowing it to run atomically—meaning that, at any given time, only one of the threads can access the protected resource.
- Using tasks, your program can run another program as a subprocess and monitor that program's execution. A task creates a separate executable entity; it differs from a thread in that it does not share memory space with the process that creates it.
- A port represents a communication channel to or from another port that typically resides in a different thread or task. These communication channels are not limited to a single machine, but can be distributed over a networked environment.
- Timers are used to send a message to an object at specific intervals. For example, you could create a timer to tell a window to update itself after a certain time interval. You can think of a timer as the software equivalent of an alarm clock.
The Foundation framework provides the functionality to manage your objects—from creating and destroying them to saving and sharing them in a distributed environment.
- Memory management
- Memory management ensures that objects are properly deallocated when they are no longer needed. This mechanism, which depends on general conformance to a policy of object ownership, automatically tracks objects that are marked for release and deallocates them at the close of the current run loop. Understanding memory management is important in creating successful Cocoa applications. We'll discuss this critical topic in depth in Chapter 4.
- Serialization and archiving
- Serializers make it possible to represent the data that an object contains in an architecture-independent format, allowing the sharing of data across applications. A specialized serializer, known as a Coder, takes this process a step further by storing class information along with the object. Archiving stores encoded objects and other data in files, to be used in later runs of an application or for distribution. This topic will also be covered in depth in Chapter 4.
- Distributed objects
- Cocoa provides a set of classes that build on top of ports and enable an interprocess messaging solution. This mechanism enables an application to make one or more of its objects available to other applications on the same machine or on a remote machine. Distributed objects are an advanced topic and are not covered in this book. For more information about distributed objects, see /Developer/Documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/DistrObjects/index.html.
File and I/O Management
Filesystem and input/output (I/O) functionality includes URL handling, file management, and dynamic loading of code and localized resources.
- File management
- Cocoa provides a set of file-management utilities that allow you to create directories and files, extract the contents of files as data objects, change your current working location in the filesystem, and more. Besides offering a useful range of functionality, the file-management utilities insulate an application from the underlying filesystem, allowing the same functionality to be used to work with files on a local hard drive, a CD-ROM, or across a network.
- URL handling
- URLs and the resources they reference are accessible. URLs can be used to refer to files and are the preferred way to do so. Cocoa objects that can read or write data from or to a file can usually accept a URL, in addition to a pathname, as the file reference.
The Foundation framework provides the ability to manage user preferences, the undo and redo of actions, data formatting, and localization to many languages. Cocoa applications can also be made responsive to AppleScript commands.
The Application Kit Framework
The Application Kit framework (or AppKit, as it's more commonly called) contains a set of over 120 classes and related functions that are needed to implement graphical, event-driven user interfaces. These classes implement the functionality needed to efficiently draw the user interface to the screen, communicate with video cards and screen buffers, and handle events from the keyboard and mouse.
Learning the many classes in the AppKit may seem daunting at first. However, you won't need to learn every feature of every class. Most of the AppKit classes are support classes that work behind the scenes helping other classes operate and with which you will not have to interact directly. Figure 1-4 shows how AppKit classes are grouped and related.
The user interface is how users interact with your application. You can create and manage windows, dialog boxes, pop-up lists, and other controls. We'll cover these topics in depth starting in Chapter 6.
- The two principle functions of a window are to provide an area in which views can be placed and to accept and distribute to the appropriate view events that the user creates through actions with the mouse and keyboard. Windows can be resized, minimized to the Dock, and closed. Each of these actions generates events that can be monitored by a program.
- A view is an abstract representation for all objects displayed in a window. Views provide the structure for drawing, printing, and handling events. Views are arranged within a window in a nested hierarchy of subviews.
- Panels are a type of window used to display transient, global, or important information. For example, a panel should be used, rather than a window, to display error messages or to query the user for a response to remarkable or unusual circumstances.
The Application Kit implements some common panels for you, such as the Save, Open, and Print panels. These common panels give the user a consistent look and feel for performing common operations.
- Controls and widgets
- Cocoa provides a common set of user-interface objects such as buttons, sliders, and browsers, which you can manipulate graphically to control some aspect of your application. Just what a particular item does is up to you. Cocoa provides menus, cursors, tables, buttons, sheets, sliders, drawers, and many other widgets.
As you'll find throughout this book, the Cocoa development tools provide quite a lot of assistance in making your applications behave according to Apple's Human Interface Guidelines. If you are interested in the details of these guidelines, read the book Inside Mac OS X: Aqua Human Interface Guidelines , commonly known as the "HIG." You can find a local copy of the HIG in /Developer/Documentation/Essentials/AquaHIGuidelines/AquaHIGuidelines.pdf.
The AppKit gives your applications ways to integrate and manage colors, fonts, and printing, and it even provides the dialog boxes for these features.
- Text and fonts
- Text can be entered into either simple text fields or into larger text views. Text fields allow entry for a single line of text, while a text view is something that you might find in a text-editing application. Text views also add the ability to format text with a variety of fonts and styles. We'll see the text-handling capabilities of Cocoa in action in Chapter 11.
- Images encapsulate graphics data, allowing you easy and efficient access to images stored in files on the disk and displayed on the screen. Cocoa handles many of the standard image formats, such as JPG, TIFF, GIF, PNG, PICT, and many more. We'll work a bit with images in Chapter 13.
- Color is supported by a variety of classes representing colors and color views. There is a rich set of color formats and representations that automatically handle different color spaces. The color support classes define and present panels and views that allow the user to select and apply colors.
The AppKit provides a number of other facilities that allow you to create a robust application that takes advantage of all the features your users expect from an application on Mac OS X.
- Document architecture
- Document-based applications, such as word processors, are some of the more common types of applications developed. In contrast to applications such as iTunes, that need only a single window to work, document-based applications require sophisticated window-management capabilities. Various Application Kit classes provide an architecture for these types of applications, simplifying the work you must do. These classes divide and orchestrate the work of creating, saving, opening, and managing the documents of an application. We'll cover the document architecture in depth in Chapter 10.
- The printing classes work together to provide the means for printing the information displayed in your application's windows and views. You can also create a PDF representation of a view. You'll see how to print in Chapter 12.
- The pasteboard is a repository for data that is copied from your application, and it makes this data available to any application that cares to use it. The pasteboard implements the familiar cut-copy-paste and drag-and-drop operations. Programmers familiar with Mac OS 9 or Carbon will recognize this functionality as the "Clipboard."
- With very little programming on your part, objects can be dragged and dropped anywhere. The Application Kit handles all the details of tracking the mouse and displaying a dragged representation of the data.
- Accessing the filesystem
- File wrappers correspond to files or directories on disk. A file wrapper holds the contents of a file in memory so it can be displayed, changed, or transmitted to another application. It also provides an icon for dragging the file or representing it as an attachment. The Open and Save panels also provide a convenient and familiar interface to the filesystem.
- A built-in spell server provides spellchecking facilities for any application that wants it, such as word processors, text editors, and email applications. Any text field or text view can provide spellchecking by using this service. We'll enable spellchecking in an application we build in Chapter 10.
- ↑ Contrary to what you may have heard elsewhere, Carbon is not doomed to fade away over time. This erroneous opinion seems to be caused by a misinterpretation of the word "transitional" to mean that the API itself will be going away, rather than meaning it is the API to use to transition older applications. Moving forward, it will remain one of the core development environments for Mac OS X. In fact, Apple engineers are striving to enable better integration between Carbon and Cocoa.
- ↑ BSD stands for Berkeley Software Distribution. For more information about BSD and its variants, see http://www.bsd.org/.
- ↑ Mac OS X 10.2 ships with localizations in the following languages: English, German, French, Dutch, Italian, Spanish, Japanese, Brazilian, Danish, Finnish, Korean, Norwegian, Swedish, and both Simplified and Traditional Chinese. Apple might add to or modify this list at any time.