Top iOS Interview Questions and Answers
Question: What is the purpose of @objc
in Swift?
Answer:
The @objc
attribute in Swift is used to expose Swift code (such as methods, properties, or classes) to the Objective-C runtime. This allows Swift code to be used with Objective-C features, such as dynamic dispatch, selectors, KVO (Key-Value Observing), and targets for actions. The @objc
attribute is essential for interoperability between Swift and Objective-C, especially when working with APIs that require Objective-C runtime features.
Here are the key purposes and use cases of @objc
in Swift:
1. Interoperability with Objective-C
-
Swift is designed to work seamlessly with Objective-C, and
@objc
is used to expose Swift code to the Objective-C runtime. This is particularly important when you’re using Objective-C frameworks (such as UIKit or Foundation) in your Swift projects, as they often rely on features like selectors, dynamic dispatch, and KVO, which are part of the Objective-C runtime.Example:
@objc class MyClass: NSObject { @objc func myMethod() { print("This method can be called from Objective-C") } }
In this example, the class
MyClass
is marked with@objc
, making it compatible with the Objective-C runtime. ThemyMethod()
is also marked with@objc
, making it accessible to Objective-C code.
2. Using Selectors
-
@objc
allows methods to be referenced as selectors. In Objective-C, selectors are used to refer to methods by name, and you can use them to perform methods dynamically, such as inperformSelector:
, or with UI actions like buttons and targets.Example:
class MyViewController: UIViewController { @objc func buttonTapped() { print("Button was tapped") } override func viewDidLoad() { super.viewDidLoad() let button = UIButton(type: .system) button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) // This makes the button tap trigger the 'buttonTapped' method } }
Here,
@objc
is necessary for the methodbuttonTapped()
to be used as a selector in theaddTarget
method.
3. Key-Value Observing (KVO)
-
In Swift,
@objc
is required for a method to work with Key-Value Observing (KVO). KVO is a mechanism in Objective-C that allows objects to observe changes to properties in other objects. Swift does not natively support KVO, but you can still use it by marking methods and properties with@objc
.Example:
@objc class MyModel: NSObject { @objc dynamic var name: String = "" } let model = MyModel() model.addObserver(self, forKeyPath: #keyPath(MyModel.name), options: .new, context: nil)
The
@objc dynamic
keyword combination is used to enable KVO for Swift properties, making them observable by Objective-C components.
4. Making Swift Methods Available for Objective-C Runtime
-
When using frameworks that rely on the Objective-C runtime (such as
UIBarButtonItem
orNSNotificationCenter
), you often need to mark Swift methods with@objc
so that they can be accessed by Objective-C code.Example:
class MyClass: NSObject { @objc func handleNotification(notification: Notification) { print("Notification received: \(notification)") } } let myClass = MyClass() NotificationCenter.default.addObserver(myClass, selector: #selector(myClass.handleNotification(notification:)), name: .someNotification, object: nil)
In this case,
handleNotification(notification:)
must be exposed to the Objective-C runtime to be used withNotificationCenter
’s selector.
5. Support for Protocols with Objective-C Requirements
-
Some Objective-C protocols or APIs (e.g.,
UITableViewDelegate
orUIActionSheetDelegate
) require methods to be marked with@objc
. When a Swift class conforms to such protocols, Swift automatically adds the@objc
attribute to required methods.Example:
@objc protocol MyDelegate: AnyObject { func didUpdateData() } class MyViewController: UIViewController, MyDelegate { @objc func didUpdateData() { print("Data has been updated.") } }
Here, the
didUpdateData
method must be exposed to the Objective-C runtime so that the protocol can be used effectively in Objective-C code.
6. Dynamic Dispatch for Swift Methods
- Swift uses static dispatch by default, which means methods are called directly based on their type at compile time. However,
@objc
enables dynamic dispatch, allowing the method to be looked up at runtime (i.e., through the Objective-C runtime). This is crucial for situations like method swizzling, where methods are dynamically replaced at runtime.
7. Using @objc
with Properties and Initializers
-
@objc
can also be used with properties and initializers to expose them to the Objective-C runtime.Example:
class MyClass: NSObject { @objc var myProperty: String = "" @objc init(property: String) { self.myProperty = property super.init() } }
In this case, both the property and the initializer are accessible from Objective-C code.
Conclusion
The @objc
attribute serves to bridge Swift code with the Objective-C runtime, making it possible for Swift code to interact with Objective-C APIs and frameworks that depend on runtime features such as selectors, dynamic dispatch, KVO, and method swizzling. It’s also essential for interoperability between Swift and Objective-C, allowing you to use features like the target-action pattern and notifications in iOS development.
Question: What is the difference between frame
and bounds
in UIKit?
Answer:
In UIKit, frame
and bounds
are both properties used to describe the size and position of views, but they are used in different contexts and represent different coordinate systems. Here’s a detailed breakdown of the differences:
1. Frame
-
The
frame
property represents the view’s position and size relative to its superview’s coordinate system. It is aCGRect
that contains both the origin (x, y) and size (width, height) of the view. -
The origin of the frame is specified in the coordinate system of the view’s superview. The
frame
is affected by the position of the view in its superview. -
The
frame
property includes:- Origin: The position of the view in its superview’s coordinate system (x, y).
- Size: The width and height of the view.
-
When to use: The
frame
is often used to determine or set a view’s position and size within its superview, especially when positioning a view within a layout.Example:
let myView = UIView() myView.frame = CGRect(x: 50, y: 100, width: 200, height: 300) // This means the view's top-left corner is at (50, 100) in the superview's coordinate system
2. Bounds
-
The
bounds
property represents the view’s own coordinate system. It is also aCGRect
, but it contains the origin and size of the view in its own local coordinate space. -
The origin of
bounds
is typically(0, 0)
, representing the top-left corner of the view in its own local coordinate system. However, it can be changed to adjust the view’s content position (e.g., in cases like scrolling). -
The
bounds
property includes:- Origin: Usually
(0, 0)
, but can be adjusted to change the view’s internal content position (e.g., for panning or scrolling). - Size: The width and height of the view, which determines its internal size.
- Origin: Usually
-
When to use: The
bounds
is often used when you need to work with the view’s content size or position within its own local coordinate system, such as when implementing custom drawing or handling internal animations.Example:
let myView = UIView() myView.bounds = CGRect(x: 0, y: 0, width: 200, height: 300) // This means the view's internal content size is 200x300
Key Differences:
Aspect | frame | bounds |
---|---|---|
Coordinate System | Relative to the superview’s coordinate system | Relative to the view’s own coordinate system |
Origin | Affects the position of the view within the superview | Typically (0, 0) , but can be modified for internal content positioning |
Use Case | Used for positioning and sizing the view within its superview | Used for the view’s internal layout or content (e.g., for drawing or transformations) |
Affect on View’s Position | Changing the frame.origin moves the view | Changing the bounds.origin moves the content inside the view |
Affect on View’s Size | Changing the frame.size changes the view’s size | Changing the bounds.size changes the view’s internal content area (doesn’t affect positioning) |
Examples to Clarify:
-
Frame Example:
If you change theframe.origin
of a view, you move the view within its superview.myView.frame.origin = CGPoint(x: 100, y: 200) // The view will now be positioned at (100, 200) within its superview
-
Bounds Example:
If you change thebounds.origin
, you affect the content inside the view, but it doesn’t move the view itself.myView.bounds.origin = CGPoint(x: 10, y: 10) // This shifts the content inside the view, but the view's position on the screen does not change
Summary:
frame
is used for positioning and sizing a view in relation to its superview.bounds
describes the view’s internal coordinate system and size, often used for custom content layout or transformations.
By understanding the difference, you can effectively manage views and their content within your app’s layout and positioning.
Read More
If you can’t get enough from this article, Aihirely has plenty more related information, such as iOS interview questions, iOS interview experiences, and details about various iOS job positions. Click here to check it out.
Tags
- IOS
- IOS interview questions
- Swift
- Memory management in iOS
- Delegates in iOS
- Core Data
- IOS networking
- Asynchronous programming in iOS
- DispatchQueue
- IOS view controller lifecycle
- Auto Layout
- Dependency Injection
- Key Value Observing (KVO)
- ViewWillAppear vs viewDidAppear
- UITableView optimization
- Synchronous vs asynchronous programming
- Throws vs rethrows in Swift
- IOS security
- Keychain Services API
- IOS performance optimization
- Protocols in Swift
- @objc in Swift
- View controller lifecycle methods
- IOS UI design
- IOS app debugging
- IOS app architecture