Split View For iPad with Auto Layout Constraints

Hey guys!. Am back with some bit old tip for Auto layout constraints to support Split View in iPad and usual view for iPhone. And It is a bit old tip but found interesting while working with this. Hence planned to share with all of you guys!. At the end, i have added bonus content. Enjoy Coding!

lyvennitha sasikumar
4 min readDec 6, 2022

Overview

As we said, We don’t need split View Controller to spit up Views in iPad and it is not the exact thing we need in most cases. Here is the output of my idea.

Auto Layout Contraints

Let’s Start with creating new project. Give Swift and StoryBoard. No Initially Got to the Main.storyBoard

Now Create a tableView with Some random stuffs like me☄️.

let data = [DataCon(name: "Helen", age: "30", gender: "Male", county: "CH", score: "4567"), DataCon(name: "Meg", age: "29", gender: "Female", county: "AI", score: "8976"), DataCon(name: "Peter", age: "35", gender: "Male", county: "MI", score: "2345"), DataCon(name: "Hoger", age: "22", gender: "Male", county: "NY", score: "9876"), DataCon(name: "Van", age: "26", gender: "Male", county: "CN", score: "4567")]
struct DataCon{
var name: String?
var age: String?
var gender: String?
var county: String?
var score: String?
}

And Here is the Delegate and DataSource Methods for tableView.

extension ViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? TableCell
cell?.titleLbl.text = data[indexPath.row].name
cell?.subTitleLbl.text = subTitleArray[indexPath.row]
return cell!
}
}

And forgot to mention the Cell class.🐖

class TableCell: UITableViewCell{
@IBOutlet weak var titleLbl: UILabel!
@IBOutlet weak var subTitleLbl: UILabel!
}

Now its time for Constraints to feed Auto Layout engine!🐈‍⬛

Am using size classes to achieve this. If you are not familiar with size classes please take a look on https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/Size-ClassSpecificLayout.html

First, For iPad we need 2 half screen for 2 controllers and not for iPhones. Here i added a Visual representation of storyboard view arrangements.

And For Initial ViewController, We need Leading, top, bottom and half width for iPad and for iPhone, no need for width and a need of trailing is there. So We can add as per we discussed using size class. Based on size class we can set Constraints. Below is the visuals.

iPad and iPhone constraints

Its time to create a Computed Variable to return whether interface is iPhone or iPad.

struct Interface{
static var interFace: InterfaceType {
if UIDevice.current.userInterfaceIdiom == .pad{
return .iPad
}
return .iPhone
}
}


enum InterfaceType{
case iPhone
case iPad
}

Its time to load second view on did select of TableView.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

let vc = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController
vc?.data = data[indexPath.row]
vc?.title = titleArray[indexPath.row]
if Interface.interFace == .iPhone{
self.navigationController?.pushViewController(vc!, animated: true)
}else{
self.addChild(vc!)
vc?.view.frame = CGRectMake(0, 0, self.viewContainer.frame.size.width, self.viewContainer.frame.size.height);
self.viewContainer.addSubview((vc?.view)!)
vc?.didMove(toParent: self)
}
}

if it is iPhone, we have to push or iPad means we have to load view in container by adding VC as child to initial view controller.

Bonus

Now i gonna share how to achieve this in SwiftUI.

Am gonna share my contentView here and explain.

var screenSize = UIScreen.main.bounds.size

struct ContentView: View {
@State var showSecondView = false
var body: some View {
NavigationView{
HStack{
VStack(spacing: 15.0) {
Image(systemName: "figure.walk")
.resizable()
.frame(width: 70.0, height: 110.0)
.foregroundColor(.purple)
if Interface.interFace == .iPhone{
NavigationLink(destination: ScreenTwo()){
Text("Tap Me")
.foregroundColor(Color.black)
}
}else{
Text("Tap Me!")
.onTapGesture {
showSecondView = true
}
}
}
.frame(width: Interface.interFace == .iPad ? screenSize.width*0.5: screenSize.width)
if Interface.interFace == .iPad{
if showSecondView{
ScreenTwo()
}else{
EmptyView()
}

}
}
.navigationBarTitle("Split View")
}

.navigationViewStyle(StackNavigationViewStyle())
}
}

And Here is the Screen Two.

struct ScreenTwo: View {
var body: some View {
Form{
VStack(spacing: 15.0) {
cellView
cellView
cellView
}
}
}

var cellView: some View{
HStack(spacing: 15.0){
Image(systemName: "figure.wave")
.resizable()
.frame(width: 60.0, height: 110.0)
.foregroundColor(.purple)
Text("Hello, world! from Screen 2")

}
}
}

Similar to Swift storyboard, we’ve gonna share half space to second view if it is iPad by setting frame like this.

.frame(width: Interface.interFace == .iPad ? screenSize.width*0.5: screenSize.width)

And the we add another view to HStack if it is iPad. And now i’ve added like on tapping action only second view gonna show. Many Types of tips available to do this easily in SwiftUI and Swift. This is one of the way. Let’s discuss in Comment section.

Happy Coding!🕊

--

--