-
Notifications
You must be signed in to change notification settings - Fork 266
Adding an Objective-C compatible API to LayoutKit #180
Conversation
|
…ayout to its own file.
This PR should be ready for review now. Two things are still missing from it: documentation comments and some support for splitting out the ObjC support code. I'll be working on the first one and investigating the second one. |
Regarding question (2) of how to avoid the overhead of this new code for Swift consumers, @chenxiao0228 's suggestion is to make a separate GitHub repo and Cocoapod named something like LayoutKit-objc. These wrapper classes and sample app in this PR would not go into this LayoutKit repo but into the new LayoutKit-objc repo/pod and the new pod would import the current LayoutKit pod. Swift consumers will continue to use this repo/pod without incurring the weight of this new code. |
LayoutKitObjCSampleApp/AppDelegate.m
Outdated
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { | ||
// Override point for customization after application launch. | ||
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds]; | ||
ViewController* viewController = [[ViewController alloc] init]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on our style guideline, we should have a space between ViewController and *, no space between * and ViewController. Please also apply the rest of them.
In this case, the style should like ViewController *viewController = [[ViewController alloc] init];
3.4 Pointer spacing
Pointers should have a space between the type and the *. There should be no space between variable names and the *.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I'll fix that.
#import <LayoutKit/LayoutKit-Swift.h> | ||
|
||
@interface RotationLayout: NSObject <LOKLayout> | ||
-(nonnull instancetype)initWithSublayout:(nonnull id<LOKLayout>)sublayout alignment:(nullable LOKAlignment *)alignment viewReuseId:(nullable NSString *)viewReuseId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you reorder the methods under the property declarations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I'll fix that.
|
||
@interface RotationLayout: NSObject <LOKLayout> | ||
-(nonnull instancetype)initWithSublayout:(nonnull id<LOKLayout>)sublayout alignment:(nullable LOKAlignment *)alignment viewReuseId:(nullable NSString *)viewReuseId; | ||
@property (readonly, nonatomic, nonnull) id<LOKLayout> sublayout; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also reorder attributes based on 3.5.1.1 Attribute ordering. Also the others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I'll fix that.
@interface RotationView: UIView | ||
@end | ||
@implementation RotationView | ||
-(instancetype)init { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-> 3.9 Method declarations and definitions
One space should be used between the - or + and the return type. Also the others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I'll fix that.
} | ||
|
||
- (void)configureWithBaseTypeView:(nonnull UIView *)baseTypeView { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this method empty?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implements the method @objc func configure(baseTypeView: View)
on the LOKLayout
protocol.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think if we should move this method to optional?
// [self.view addSubview:tableView]; | ||
// self.adapter = [[LOKReloadableViewLayoutAdapter alloc] initWithTableView:tableView]; | ||
// tableView.delegate = self.adapter; | ||
// tableView.dataSource = self.adapter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you comment out those code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I was using it to verify that the wrapper worked for UITableView, I'll remove it.
// tableView.delegate = self.adapter; | ||
// tableView.dataSource = self.adapter; | ||
|
||
LOKSizeLayout *cellLayout = [[LOKSizeLayout alloc] initWithMinWidth:self.view.bounds.size.width |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered creating a few convenience initializers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are too many parameters with default properties, so making convenience initializers even for the common combinations would be too many. A builder pattern will be more appropriate and that's coming in a separate change.
@@ -30,10 +30,21 @@ open class BaseLayout<V: View> { | |||
return config != nil | |||
} | |||
|
|||
private let viewClass: View.Type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason for this is objective-c doesn't support V
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Objective C has some support for generics but it's mostly for defining neat interfaces for Swift, and some mild type checking on Obj C side, not nearly as full featured as Swift generics.
public class LOKBaseLayout: NSObject, LOKLayout { | ||
let layout: Layout | ||
|
||
init(layout: Layout) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We keep all init
internally for wrapper use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
|
||
import UIKit | ||
|
||
@objc public class LOKButtonLayout: LOKBaseLayout { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering why we can't directly create objective-c classes for wrappers? With objective-c wrappers, it might be much faster with generating swift interfaces. Also, we can separate them to different pod, so the LayoutKit
is purely swift LayoutKit
without objc support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Swift was chosen for these wrappers since this codebase already uses Swift and for simplicity I'd like to keep it single-language. I doubt there would much difference in speed, either at editing, build, or run time.
Regarding Pods, I'm planning to exclude these wrappers from the current Pod and include them in a new Pod.
Additional to @chenxiao0228 comment, we can still keep them in the same repo, but 2 x pods and that would be easier to manage. |
Also, we need to setup the test for wrappers because the current CI doesn't compile objective-c wrappers |
$ pod lib lint -> LayoutKit (6.0.1) LayoutKit passed validation. -> LayoutKitObjC (6.0.1) LayoutKitObjC passed validation.
|
||
import CoreGraphics | ||
|
||
class ReverseWrappedLayout: Layout { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems ReverseWrappedLayout.swift
and WrappedLayout
isn't being used for the public. Could you create a Internal
folder for those two classes?
} | ||
|
||
- (void)configureWithBaseTypeView:(nonnull UIView *)baseTypeView { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think if we should move this method to optional?
image: UIImage?, | ||
imageSize: CGSize, | ||
font: UIFont? = nil, | ||
contentEdgeInsets: NSValue?, // UIEdgeInsets |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of NSValue
, we might consider wrapping it a class. To compare with NSValue
, it would be easier to understand and configure.
This is related to issue #178 regarding adding support for Objective-C consumers.
This objc-api branch is now ready for review.
Two of the open questions are:
The builders for (1) can be added as a separate follow-up change.
Currently working on figuring out what we can do for (2).