Model2App是一个简单的库,可让您快速基于Swift中定义的数据模型生成CRUD iOS应用。 ( CRUD创建读取更新删除)。是否曾经想为您的下一个很棒的iOS应用程序快速验证数据模型吗? Model2App使您可以通过生成具有持久层,验证和更多功能的全部工作应用程序来节省小时/天。只需定义您的模型,点击⌘ + R并享受您的应用。 ?
Model2App在引擎盖下使用领域❤️,可以将其视为开发活动的扩展,尤其是在定义或验证大型项目的数据模型的阶段。
✅基于应用程序定义的类的应用菜单
✅对象列表视图,每个模型类
✅基于模型属性列表,用于创建,更新和查看给定类的对象的动态对象视图
✅基于属性类型或已声明的控制类型的对象属性单元格(请参阅下面的支持的控制类型)
✅逻辑处理不同的控制类型以更改对象属性的值
✅使用一组预定义的规则或使用闭合来创建/更新对象的验证逻辑,以创建/更新对象
✅在本地存储( Realm )中持续创建的对象的逻辑
✅调用对象更新会话和删除对象的逻辑
✅在Object属性的情况下,用于在对象之间设置关系的逻辑
✅针对其他对象引用的对象(逆关系)的对象的部分
✅用于从给定对象视图创建相关对象的逻辑
✅相关对象之间的逻辑到遍历(无限)
✅开箱即用缩放和缩放导航动画
✅&一堆更多的小功能
✅调整应用程序菜单(布局,订单,背景,菜单项的图标/布局/alphan,字体名称/尺寸/颜色,动画等)
✅从提供的捆绑包( MenuIcons )中选择任何菜单项图标,提供您自己的菜单,或者让Model2App为您选择一个
✅调整对象列表视图(单元格布局/背景,显示的对象属性,图像布局,动画等)
✅调整对象视图属性单元格(单元格布局/背景,字体名称/尺寸/颜色,图像布局,占位符等)
✅调整对象视图相关对象的标头(标题布局/背景,字体名称/尺寸/颜色)
✅调整选择器列表视图(单元格布局/背景,字体名称/尺寸/颜色)
✅从应用菜单中隐藏特定类或从对象视图隐藏给定类的特定属性
✅调整默认动画配置:演示/解雇动画持续时间,阻尼比或初始弹簧速度
✅指定是否应圆形列出图像视图
✅支持iPhone和iPad
✅支持肖像和景观取向
✅验证您的数据模型的声明关系并声明了属性的控制类型
✅启用使用表情符号字符作为菜单图标图像
✅灵活性和可扩展性:除了可以覆盖的M2AConfig类中定义的配置参数外,用于核心应用程序功能的大多数类和方法都具有open访问修饰符,因此您可以在应用程序中自定义或扩展Model2App框架的选定部分
TextField
✏️ NumberField
FloatDecimalField
✏️ DoubleDecimalField
✏️ CurrencyField
✏️ PhoneField
EmailField
✏️ PasswordField
URLField
ZIPField
✏️ Switch
DatePicker
✏️ TimePicker
DateTimePicker
TextPicker
✏️ ObjectPicker
ImagePicker
✅xcode 10.1+
✅快速4.2+
Model2App可通过可可录和迦太基提供。
为了通过Cocoapods安装Model2App ,只需将以下行添加到您的podfile:
pod 'Model2App'然后运行以下命令:
$ pod install为了通过迦太基安装Model2App ,只需将以下行添加到您的Cartfile:
github "Q-Mobile/Model2App" ~> 0.1.0
然后运行以下命令:
$ carthage update请记住Carthage/Build/*除了迦太基*.framework其他标准步骤Model2App.framework
安装Model2App之后,只需通过子类ModelClass来定义数据模型,如下所示,或如下示例应用程序中可用的示例应用程序( Model2AppTestApp )中可用,然后点击⌘ + R 。 (注意:下面可见的示例数据模型只是示例应用程序中的一个小摘录,请参阅Model2AppTestApp源以获取更扩展的模型)
@ objcMembers class Company : ModelClass {
dynamic var name : String ?
dynamic var phoneNumber : String ?
dynamic var industry : String ?
}
@ objcMembers class Person : ModelClass {
dynamic var firstName : String ?
dynamic var lastName : String ?
dynamic var salutation : String ?
dynamic var phoneNumber : String ?
dynamic var privateEmail : String ?
dynamic var workEmail : String ?
let isKeyOpinionLeader = OptionalProperty < Bool > ( )
dynamic var birthday : Date ?
dynamic var website : String ?
dynamic var note : String ?
dynamic var picture : Data ?
dynamic var company : Company ?
}
@ objcMembers class Deal : ModelClass {
dynamic var name : String ?
let value = OptionalProperty < Int > ( )
dynamic var stage : String ?
dynamic var closingDate : Date ?
dynamic var company : Company ?
} 如果您想自定义默认类/属性配置,只需覆盖由ModelClass定义的某些或全部计算的类型属性:
@ objcMembers class Company : ModelClass {
// (model properties defined earlier)
override class var pluralName : String { return " Companies " }
override class var menuIconFileName : String { return " users " }
override class var menuOrder : Int { return 2 }
override class var inverseRelationships : [ InverseRelationship ] {
return [
InverseRelationship ( " employees " , sourceType : Person . self , sourceProperty : #keyPath ( Person . company ) ) ,
InverseRelationship ( " deals " , sourceType : Deal . self , sourceProperty : #keyPath ( Deal . company ) )
]
}
override class var propertyConfigurations : [ String : PropertyConfiguration ] {
return [
#keyPath ( name ) : PropertyConfiguration (
placeholder : " Enter company name " ,
validationRules : [ . Required ]
) ,
#keyPath ( phoneNumber ) : PropertyConfiguration (
placeholder : " Enter phone number "
) ,
#keyPath ( industry ) : PropertyConfiguration (
controlType : . TextPicker ,
pickerValues : [ " Consulting " , " Education " , " Financial Services " , " Government " , " Manufacturing " , " Real Estate " , " Technology " , " Other " ]
)
]
}
}
@ objcMembers class Person : ModelClass {
// (model properties defined earlier)
override class var pluralName : String { return " People " }
override class var menuIconFileName : String { return " user-1 " }
override class var menuIconIsFromAppBundle : Bool { return true }
override class var menuOrder : Int { return 1 }
override class var listViewCellProperties : [ String ] {
return [ #keyPath ( picture ) , #keyPath ( firstName ) , #keyPath ( lastName ) ]
}
override class var listViewCellLayoutVisualFormats : [ String ] {
return [
" H:|-10-[picture]-[firstName]-5-[lastName(>=50)]-| " // OR: (with slightly weaker readability but more safe): "H:|-10-[#keyPath(picture)]-[#keyPath(firstName)]-5-[#keyPath(lastName)(>=50)]"
]
}
override class var propertyConfigurations : [ String : PropertyConfiguration ] {
return [
#keyPath ( firstName ) : PropertyConfiguration (
controlType : . TextField ,
placeholder : " Enter first name " ,
validationRules : [ . Required ]
) ,
#keyPath ( lastName ) : PropertyConfiguration (
controlType : . TextField ,
placeholder : " Enter last name " ,
validationRules : [ . Required ]
) ,
#keyPath ( salutation ) : PropertyConfiguration (
controlType : . TextPicker ,
pickerValues : [ " Mr. " , " Ms. " , " Mrs. " , " Dr. " , " Prof. " ] ,
validationRules : [ . Required ]
) ,
#keyPath ( phoneNumber ) : PropertyConfiguration (
controlType : . PhoneField ,
placeholder : " Enter phone number " ,
validationRules : [ . MinLength ( length : 9 ) , . MaxLength ( length : 12 ) ]
) ,
#keyPath ( privateEmail ) : PropertyConfiguration (
controlType : . EmailField ,
placeholder : " Enter email address " ,
validationRules : [ . Email ]
) ,
#keyPath ( workEmail ) : PropertyConfiguration (
controlType : . EmailField ,
placeholder : " Enter email address " ,
validationRules : [ . Required , . Email , . Custom ( isValid : { object in
if let workEmail = object [ #keyPath ( workEmail ) ] as? String ,
let privateEmail = object [ #keyPath ( privateEmail ) ] as? String ,
workEmail == privateEmail {
UIUtilities . showValidationAlert ( " Work Email cannot be the same as Private Email. " )
return false
}
return true
} ) ]
) ,
#keyPath ( birthday ) : PropertyConfiguration (
controlType : . DatePicker ,
validationRules : [ . Required ]
) ,
#keyPath ( website ) : PropertyConfiguration (
controlType : . URLField ,
placeholder : " Enter URL " ,
validationRules : [ . URL ]
) ,
#keyPath ( note ) : PropertyConfiguration (
controlType : . TextField ,
placeholder : " Enter note " ,
validationRules : [ . MaxLength ( length : 1000 ) ]
) ,
#keyPath ( company ) : PropertyConfiguration (
validationRules : [ . Required ]
) ,
#keyPath ( picture ) : PropertyConfiguration (
controlType : . ImagePicker
)
]
}
}
@ objcMembers class Deal : ModelClass {
// (model properties defined earlier)
override class var pluralName : String { return " Deals " }
override class var menuIconFileName : String { return " money " }
override class var listViewCellProperties : [ String ] {
return [ #keyPath ( name ) , " value " , #keyPath ( stage ) ]
}
override class var listViewCellLayoutVisualFormats : [ String ] {
return [
" H:|-10@750-[name(>=50)]-(>=10)-[value(>=50)]-| " ,
" H:|-10@750-[stage]-(>=10)-[value] " ,
" V:|-10@750-[value]-10@750-| " ,
" V:|-10@750-[name]-[stage]-| "
]
}
override class var propertyConfigurations : [ String : PropertyConfiguration ] {
return [
#keyPath ( name ) : PropertyConfiguration (
controlType : . TextField ,
placeholder : " Enter deal name " ,
validationRules : [ . Required ]
) ,
" value " : PropertyConfiguration (
controlType : . CurrencyField ,
placeholder : " Enter deal value " ,
validationRules : [ . Required ]
) ,
#keyPath ( stage ) : PropertyConfiguration (
controlType : . TextPicker ,
pickerValues : [ " Prospecting " , " Qualified " , " Reviewed " , " Quote " , " Won " , " Lost " ] ,
validationRules : [ . Required ]
) ,
#keyPath ( company ) : PropertyConfiguration (
validationRules : [ . Required ]
)
]
}
} ModelClass类型类型属性: displayName此类显示名称。如果未提供,请从班级名称推断
✏️ pluralName -此类的复数名称。用于命名对象或菜单项列表。如果未提供, <ClassName> - List
✏️ menuIconFileName应用程序的根菜单中用于菜单图标的图像文件的名称
✏️ menuIconIsFromAppBundle fromappBundle-指定Model2App是否应该在主应用程序捆绑包中查找菜单图标文件。如果是false ,则使用Model2App的捆绑包
✏️ menuOrder订单 - 该类的菜单项在应用程序的根菜单中propertyConfigurations此类属性配置字典
✏️ inverseRelationships - 此类的反关系列表(如果有其他类别的to-one ,则应定义,如果您想提出相关对象的一部分)
listViewCellProperties此类列表查看单元格中使用的属性列表。应包含listViewCellLayoutVisualFormats中指定的所有属性listViewCellLayoutVisualFormats使用Apple的自动布局视觉格式语言列表查看单元格的视觉格式列表isHiddenInRootView指定给定模型类是否应隐藏在应用程序的根菜单中(对于仅应在相关对象部分显示的儿童实体,对于给定的对象有用)
PropertyConfiguration的属性: controlType指定用于此属性的UI控件的类型
✏️ placeholder - 指定该属性未提供值时使用的占位符值pickerValues指定此属性的潜在选择器值列表。仅适用于TextPicker contryType
✏️ validationRules - 指定此属性的验证规则列表(创建此类的新对象时进行评估)
✏️is isHidden指定该属性是否应隐藏在UI上
ValidationRule ): Required
✏️ MinLength(length: Int)
✏️ MaxLength(length: Int)
✏️Minvalue MinValue(value: Double)
MaxValue(value: Double)
✏️ Email
URL
Custom(isValid: (ModelClass) -> Bool)
M2AConfig类定义了可以由应用程序选择的默认应用程序配置。请参阅Model2AppTestApp示例应用中的M2AConfig类源和AppConfig.swift文件。
Model2App在引擎盖下使用领域,因此它具有与模型定义相似的考虑:@objc dynamic var (或使用objcMembers声明类本身,只是dynamic var ),除了OptionalProperty Property(用于数字/BOOL)外,应仅使用fer let声明。OptionalProperty (领域RealmOptional的别名)完成的。 此存储库中的Model2AppTestApp目录包含一个示例应用程序,该应用程序定义了非常简单的CRM相关数据模型。 Open Model2AppTestApp/Model2AppTestApp.xcworkspace并运行此测试应用程序,以查看将Model2App库应用于示例数据模型的影响。
Model2App的0.1.0版本未处理数据模型迁移,因此,如果您在初始应用程序启动后更改数据模型,您将获得错误,并且必须在下一个启动之前删除该应用程序,以查看更新的模型。处理模型迁移是在路线图中计划的,以备将来发行。
OptionalProperty Property属性,则不能使用#keyPath安全引用给定属性(例如,来自propertyConfigurations或listViewCellProperties定义)
Model2App的0.1.0版包含一组有限的功能。有许多功能可以扩展其价值:
☘️在对象列表视图上搜索
☘️过滤对象列表视图
☘️在对象列表视图上排序
☘️处理级联删除
☘️处理模型迁移
☘️支持控制类型:“滑块”
☘️支持控制类型:“ TextView”
☘️支持控制类型:“按钮”
☘️支持一对多关系(到目前为止,仅支持一对多关系)
☘️选项使用表情符号作为菜单项图标,而不是图像
☘️...等等!敬请关注! ❤️
???遵循以下准则,可以随意通过创建拉动请求来为Model2App做出贡献:
Model2App? Model2App使用的图标是由Flaticon的Lucy G设计的
特别感谢领域背后的所有人
? karol kulesza(@karolkulesza)
? Model2App可根据MIT许可获得。有关更多信息,请参见许可证文件。