天天看點

Mac OS app 用 StoryBoard開發的一點感想

Mac OS app 用 StoryBoard開發的一點感想。

前提

最近在學習app的逆向,準備自己搞一個app,然後用逆向工具對其進行惡搞一下。

選擇

糾結在于用Mac app還是 IOS app,糾結了一下,選擇了Mac app。

原因:

  • 開發體驗

    搞Mac app不用起模拟器。15年的閹割版的Mac跑起模拟器來那叫一個吵和卡。

  • 開發效率

    電腦不卡,開發效率就會高一點,主要是心情會好,不然太卡的話,寫代碼的時候特别煩。

  • 簡單

    XCode打開,直接run就好了。

趟坑

  • 以為的簡單并不簡單

    以為開發來說和和IOS的差不多,但是實際是關于Mac app的開發介紹的文章很少、app 數量也很少

  • 在過去Objective-C一直是蘋果生态裡的重要語言,最近幾年雖說主推Swift,但是應該也不至于死掉吧?

    沒想到現在用Objective-C開發的實在是太少少了

  • XCode 11

    嗯,你沒看錯,就是XCode11,這個版本的XCode UI應該是更新了,是以我能找到的文章都是Objective-C寫的,那時候的XCode UI和現在的UI不一樣

  • StoryBoard

    負責UI層展示,這個有很多magic的操作,找不到那就JJ了,完全玩不動呀,當然蘋果現在主推SwiftUI,是以。。。用的時候一直覺的微軟是真的好呀,winform拖控件是真的簡單。

    • 給按鈕綁定個單擊事件

      我搞了快一天,一直找不到storyboard的UI怎麼和controller關聯起來的,然後自然也找不到按鈕的點選事件

      • 如何關聯controller
        Mac OS app 用 StoryBoard開發的一點感想
      #import <Cocoa/Cocoa.h>
      @interface ViewController : NSViewController
      @end
                 
      • 如何給按鈕添加點選事件
        1. 在xcode中打開storyboard檔案,找到你要添加點選事件的按鈕。
        2. 在左側檔案清單中找到關聯的那個controller,按住option鍵然後點選,出現雙屏,一屏是storyboard,一屏是代碼
        3. 按住control鍵,點着那個按鈕拖向代碼檔案。
        4. 出現dialog,填上你的内容
          Mac OS app 用 StoryBoard開發的一點感想
        5. 結束

          簡單的gif

          Mac OS app 用 StoryBoard開發的一點感想

app的功能

  • 一個添加頁面
    • 一個清除按鈕,點選之後清除頁面輸入的資料
    • 一個确定按鈕,點選之後會将資訊攜帶到詳情展示頁面
    • 兩個label,兩個輸入框
    • 設定view的背景色
      Mac OS app 用 StoryBoard開發的一點感想
  • 一個詳情展示頁面
    • 展示上個頁面填寫的内容
      Mac OS app 用 StoryBoard開發的一點感想

遇到問題

  1. 代碼裡如何或者輸入框裡的内容

    在ViewController.h中綁定兩個屬性,然後在impl中可以直接使用

    做法:還是分屏,然後ctrl拖拽,之後就會生成兩個屬性

// interface
#import <Cocoa/Cocoa.h>

@interface ViewController : NSViewController
@property (weak) IBOutlet NSTextField *nameTextField;
@property (weak) IBOutlet NSTextField *phoneTextField;
@end

//impl
#import "ViewController.h"

@implementation ViewController

@synthesize nameTextField;
@synthesize phoneTextField;

// 擷取姓名輸入框的内容
- (NSString *)getName {
    return [nameTextField stringValue];
}
// 擷取手機号輸入框的内容
- (NSString *)getPhone {
    return [phoneTextField stringValue];
}
//清除輸入框内容
- (IBAction)CancelClicked:(id)sender {
    [nameTextField setStringValue:@""];
    [phoneTextField setStringValue:@""];
}
// other code
@end

           
  1. 如何設定背景色

    拓展NSView,添加設定背景色方法,然後綁定到UI層,

    • 實作代碼
// interface
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

@interface NSView (backGroundColor)
-(void) setBackGroundColor: (NSColor *) color;
@end

//impl
#import "backgroundColor.h"

@implementation NSView (backgroundColor)
- (void)setBackGroundColor:(NSColor *)color {
    [self setWantsLayer:YES];
    self.layer = [CALayer layer];
    [self.layer setBackgroundColor:[color CGColor]];
}
@end
           
  • 綁定

    輸入名稱和拓展的方法一緻,省掉set方法

Mac OS app 用 StoryBoard開發的一點感想
  1. 如何點選确定跳轉到另一個界面呢

    在storyboard界面找到按鈕,ctrl拖到它點選之後要跳轉的界面

Mac OS app 用 StoryBoard開發的一點感想

之後出現這個dialog

Mac OS app 用 StoryBoard開發的一點感想

這樣就完成了。

  1. 如何将值傳過去呢

    先看一下兩個界面之間建立了啥

    Mac OS app 用 StoryBoard開發的一點感想

是個NSStoryboardSegue類型的東西

@interface NSStoryboardSegue : NSObject

/* NSStoryboardSegue instances have optional identifiers that can be assigned in Interface Builder. These identifiers can be used in overrides of -[NSViewController prepareForSegue:sender:] to differentiate segues. */
@property (nullable, readonly, copy) NSStoryboardSegueIdentifier identifier;

/* Subclasses of NSStoryboardSegue can use this property to access the source view or window controller that is being segued away from. */
@property (readonly, strong) id sourceController;

/* Subclasses of NSStoryboardSegue can use this property to access the destination view or window controller that\'s being segued to. This property is also essential for overrides of -[NSViewController prepareForSegue:sender:], which is passed to the source view controller. This property allows the receiver of -[NSViewController prepareForSegue:sender:] to access and pass configuration data to the destination controller. */
@property (readonly, strong) id destinationController;

@end
           

有sourceController和destinationController,是不是很明确了

  • 步驟

    1. 重寫SourceController(

    NSViewController

    )的

    - (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(nullable id)sender

    方法
```objective-c
  - (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(nullable id)sender {
        DetailController *detailController = [[DetailController alloc] init]; // destinationController
        detailController = segue.destinationController;
        UserInfo *userInfo = [[UserInfo alloc] init];
        [userInfo setName:[self getName] andPhone:[self getPhone]];
        detailController.userInfo= userInfo;//設定要傳遞的值
    }  
```
2. destinationController
添加一個屬性接收傳遞的值,在`viewDidLoad`方法裡将傳遞的值給指派到view上
```objective-c
// interface
    @interface DetailController : NSViewController
    @property UserInfo *userInfo;
    @property (weak) IBOutlet NSTextField *nameTextField;
    @property (weak) IBOutlet NSTextField *phoneTextField;
    @end


// impl
    @implementation DetailController
    @synthesize userInfo;
    @synthesize nameTextField;
    @synthesize phoneTextField;

    - (void)viewDidLoad {
        [super viewDidLoad];
        [nameTextField setStringValue:[userInfo name]];
        [phoneTextField setStringValue:[userInfo phone]];
    }
    @end
```
           

結束

Mac OS app 用 StoryBoard開發的一點感想

遇到錯誤

resource fork, Finder information, or similar detritus not allowed

Command CodeSign failed with a nonzero exit code

解決方法:進入項目的根目錄執行

xattr -cr .

引用

  • Mac Os DarkMode
  • iOS - Code Sign Error in macOS High Sierra Xcode - resource fork, Finder information, or similar detritus not allowed - Stack Overflow

源碼

https://github.com/1483523635/simple-MacOS-app

部落格原始位址

https://github.com/1483523635/blogs/blob/master/MacOSApp/StoryBoard.md