

Qiita の「Swiftで UITextField から UIDatePicker を呼び出して
Toolbarに完了ボタンなどを用意する」をswift3で使おうとして次の２点がエラーになってしまいます。改善方法をご教示いただけますか。  
1\. 34行目

[code]

    // UIToolBarの設定
    toolBar = UIToolbar(frame: ***CGRectMake***(0, self.view.frame.size.height/6, self.view.frame.size.width, 40.0))
    
[/code]

`CGRectMake`を`CGRect`にすると

> Argument labels do not match any....

とエラーになります。これはどのように修正するのでしょうか。

2.`//「今日」を押すと今日の日付をセットする」`の84行目を Fix it Replaceで修正すると

[code]

    ***let comps: NSDateComponents = calender.components(NSCalendar.Unit.YearCalendarUnit|NSCalendar.Unit.MonthCalendarUnit|NSCalendar.Unit.DayCalendarUnit|NSCalendar.Unit.HourCalendarUnit|NSCalendar.Unit.MinuteCalendarUnit|NSCalendar.Unit.SecondCalendarUnit|NSCalendar.Unit.WeekdayCalendarUnit, fromDate: date)***
    
[/code]

が

> No '|' candidates produce the expected contextual result type
> 'NSCalendarUnit'

とエラーになります。どのように修正するのでしょうか。

<http://qiita.com/matsuhisa_h/items/4bb9803828efb89e0305>


CC BY-SA 3.0
2016-12-11T05:23:28.243
31083
2016-12-11T12:10:58.837
2016-12-11T12:10:58.837
15185
19879
question
xcode swift3
「Swiftで UITextField から UIDatePicker を呼び出す」をswift3に変換する際のエラー


ご質問を書かれる場合は、出来るだけ「状況が再現できる必要十分な情報」を(テキストとして)掲載されるようにしてください。リンクを掲載するのは補助的な情報としては有用ですが、将来リンク切れなどがあると、あなたの質問が(将来の読者にとって)意味をなさなくなってしまいます。

で、あなたのご質問項目を読むと「リンク先のコードをそのままコピペしてXcodeからオートコレクトのサジェスチョンが表示されるところだけ、その修整を当てた状態」になっているようです。

ちなみに **それだけではリンク先のコードを正しく動くようにはできません**
。あなたが他の修正をうまく当てたことを祈ってますが、上に書いたように必要な情報が無いのでその部分は何とも言えません。

* * *

(1) `CGRectMake`

※結論が早く見たいなら、「 **結論として**
」の部分まですっ飛ばしてください。自分の開発スキルを磨きたいなら、リンク先を含め全部に目を通していただきたいところですが。

Swift
3では、多くのインスタンス生成用の関数が削除されました。その殆どは「コンストラクタで代用できるから」です。表題の関数は`CGRect`生成用の関数ですから、`CGRect`のコンストラクタの中に代用できる機能があるはず、と言うことになります。

### [`CGRect`](http://CGRect)

> ## Creating Rectangle Values
[code]

>     init(origin: CGPoint, size: CGSize)
>  
[/code]

>
> Creates a rectangle with the specified origin and size.
[code]

>     init(x: Double, y: Double, width: Double, height: Double)
>  
[/code]

>
> Creates a rectangle with coordinates and dimensions specified as  
>  floating-point values.
[code]

>     init(x: Int, y: Int, width: Int, height: Int)
>  
[/code]

>
> Creates a rectangle with coordinates and dimensions specified as  
>  integer values.
[code]

>     init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat)
>  
[/code]

>
> Creates a rectangle with coordinates and dimensions specified as  
>  CGFloat values.

英語の説明の部分はよくわからなくても、`CGRectMake`が`CGFloat`型のパラメータを4つ取る関数だということが分かっていれば、最後の`init(x:
CGFloat, y: CGFloat, width: CGFloat, height: CGFloat)`が使えるということがわかると思います。

**結論として** こんな風に書き換えることになります。

[code]

        toolBar = UIToolbar(frame: CGRect(x: 0, y: self.view.frame.size.height/6, width: self.view.frame.size.width, height: 40.0))
    
[/code]

* * *

(2) `NSCalendar.Unit`

※結局`NSCalendar.Unit`は要らないので早く結論が見たければ「 **さらに修正** 」の辺りまで飛ばしてください。

###
[`NSCalendar.Unit`](https://developer.apple.com/reference/foundation/nscalendar.unit)

以前は単なる整数値だった`NSCalendarUnit`型は`OptionSet`の`NSCalendar.Unit`型として移入されるようになりました。`OptionSet`に適合する型では以前の`|`に相当する演算として`Set`型に近い記法(リテラルだけなら`Array`型とも同じ)を使うのですが、ここではその修正をするだけではなく、以下の修正も一緒に行うことにさせてもらいます。

[Using Swift with Cocoa and Objective-C (Swift
3.0.1)](https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/BuildingCocoaApps/index.html#//apple_ref/doc/uid/TP40014216)の中の[Foundation](https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID211)から
**Bridged Types** の部分をご覧になってください。

Swift 3では、参照型である幾つかのデータ型に対応する値型のデータ型が追加されています。今回のコードの中から抜粋すると…

>
[code]

>     NSCalendar       Calendar
>     NSDateComponents DateComponents
>     NSDate           Date
>     NSLocale         Locale
>  
[/code]

(`NSDateFormatter`は?、と思われるかもしれませんが、こちらは「クラス名から`NS`が取れただけ」でまた別物です。)

現在のSwiftはこれらのデータ型に対して、積極的に値型の方を使うような修正はサジェストしてこないことが多いようですが、できるだけ将来に通じるSwift的なコードにしたければ、全部値型の方を使用することをお勧めしておきます。

そういったことを当てはめると、リンク先の`dateToString`メソッドはこんな感じになったのですが…

[code]

    func dateToString(date: Date) -> String {
        //Swiftが型推論を絶対に間違えない場所では、型名は省略
        //OptionSet型やenumの定数は適切な場所では型名部分を省略できる(Calendar.Identifier.gregorian -> .gregorian)
        let calender = Calendar(identifier: .gregorian)
        //OptionSet型では`Set`型風に定数リテラルを使用する、型名部分も省略可
        let comps = calender.dateComponents([.year, .month, .day, .hour, .minute, .second, .weekday], from: date)
        
        //DateFormatterは参照型なので、letが適切
        let date_formatter = DateFormatter()
        //`weekdays`は`String?`(=`Optional<String>`)の配列になってしまうと言う非常に悪い書き方、しかも内容の変更はしないのだから`let`を使うべき
        let weekdays: Array  = [nil, "日", "月", "火", "水", "木", "金", "土"]
        
        date_formatter.locale     = Locale(identifier: "ja")
        date_formatter.dateFormat = "yyyy年MM月dd日（\(weekdays[comps.weekday!])） "
        
        return date_formatter.string(from: date)
    }
    
[/code]

とここまでコードを書いて、気がついたのですが、上記のコードで`Date`型の値を文字列に変換すると、曜日を入れたかったのであろう部分によくわからない変な値が埋まってしまいます。

そもそも極めて標準的な曜日名を入れるのに`weekdays`なんて自前の配列を用意する必要はありませんし、そうするとあなたが苦労された`NSDateComponents`を使用する必要も無いということになります。

(記事の日付はSwift
2.1時代のものですが、これはその頃のSwiftを使っていたとしても発生するバグなので、「動作確認が十分なされていないコードを掲載している」と言うことになります。)

そこら辺を **さらに修正** するとこんなコードが出来上がります。

[code]

    func dateToString(date: Date) -> String {
        //DateFormatterは参照型なので、letが適切
        let date_formatter = DateFormatter()
        //日本語Localeを使用して曜日の1文字表記をしたいならweekdaysなんて配列はいらない
        
        date_formatter.locale     = Locale(identifier: "ja")
        date_formatter.dateFormat = "yyyy年MM月dd日（E） " //<-`E`は曜日出力用のフォーマット文字
        
        return date_formatter.string(from: date)
    }
    
[/code]

※上記のコードを使用するなら、関連して他の部分を若干修正する必要があります。

ネット上のSwift情報には「いくらSwift2の時代でもこの書き方はないだろう」とか、上記のようにろくに動作確認もされていないと思われるコードが氾濫しています。(これはお勧めできない、どこから、全く動かないという記事がGoogleの上位に来たりします…。)本当にこんなやり方で正しいんだろうかというのを判断できるだけのセンスを磨いていってください。

なお、よく探すと同じ著者自身がSwift 3版の記事を既に公開されているという場合もあります。Swift 3で開発されるなら、初めからSwift
3用の記事を(少々時間をかけてでも)探し出した方が、余計なことに煩わされずに済みますよ。

* * *

最初に書いたようにこれだけではリンク先記事のコードを動くようにはできないのですが、この回答に書かれたこと自体に疑問点や誤りなどがありましたらコメントなどで、まだ動くようにできない部分が残りましたら別スレッドで新たな質問として、お知らせください。


CC BY-SA 3.0
2016-12-11T07:14:59.160
31084
2016-12-11T07:20:51.430
2020-06-17T08:14:45.997
-1
13972
31083
answer